Passed
Push — ofaj ( 31cfb2...656ded )
by
unknown
21:17 queued 08:44
created

send_notifications()   C

Complexity

Conditions 12
Paths 25

Size

Total Lines 43
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 27
nc 25
nop 3
dl 0
loc 43
rs 6.9666
c 0
b 0
f 0

How to fix   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', $courseCode);
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 ($content == 'forumcategory') {
1467
        $table = $table_categories;
1468
        $sort_column = 'cat_order';
1469
        $id_column = 'cat_id';
1470
        $sort_column = 'cat_order';
1471
    } elseif ($content == 'forum') {
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 = ".intval($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->getUserId();
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,
3513
    $qualify_time,
3514
    $session_id
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 = (int) $session_id;
3521
    $thread_id = (int) $thread_id;
3522
    $user_id = (int) $user_id;
3523
    $currentUserId = api_get_user_id();
3524
    $qualify_time = Database::escape_string($qualify_time);
3525
3526
    if ($user_id == strval(intval($user_id)) &&
3527
        $thread_id == strval(intval($thread_id)) &&
3528
        $thread_qualify == strval(floatval($thread_qualify))
3529
    ) {
3530
        // Testing
3531
        $sql = "SELECT thread_qualify_max FROM $table_threads
3532
                WHERE c_id = $course_id AND thread_id=".$thread_id;
3533
        $res_string = Database::query($sql);
3534
        $row_string = Database::fetch_array($res_string);
3535
        if ($thread_qualify <= $row_string[0]) {
3536
            if ($threadInfo['thread_peer_qualify'] == 0) {
3537
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3538
                        WHERE
3539
                            c_id = $course_id AND
3540
                            user_id = $user_id AND
3541
                            thread_id = ".$thread_id;
3542
            } else {
3543
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3544
                        WHERE
3545
                            c_id = $course_id AND
3546
                            user_id = $user_id AND
3547
                            qualify_user_id = $currentUserId AND
3548
                            thread_id = ".$thread_id;
3549
            }
3550
3551
            $result = Database::query($sql);
3552
            $row = Database::fetch_array($result);
3553
3554
            if ($row[0] == 0) {
3555
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3556
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3557
                Database::query($sql);
3558
                $insertId = Database::insert_id();
3559
                if ($insertId) {
3560
                    $sql = "UPDATE $table_threads_qualify SET id = iid
3561
                            WHERE iid = $insertId";
3562
                    Database::query($sql);
3563
                }
3564
3565
                return 'insert';
3566
            } else {
3567
                saveThreadScoreHistory(
3568
                    '1',
3569
                    $course_id,
3570
                    $user_id,
3571
                    $thread_id
3572
                );
3573
3574
                // Update
3575
                $sql = "UPDATE $table_threads_qualify
3576
                        SET
3577
                            qualify = '".$thread_qualify."',
3578
                            qualify_time = '".$qualify_time."'
3579
                        WHERE
3580
                            c_id = $course_id AND
3581
                            user_id=".$user_id." AND
3582
                            thread_id=".$thread_id." AND
3583
                            qualify_user_id = $currentUserId
3584
                        ";
3585
                Database::query($sql);
3586
3587
                return 'update';
3588
            }
3589
        } else {
3590
            return null;
3591
        }
3592
    }
3593
}
3594
3595
/**
3596
 * This function shows qualify.
3597
 *
3598
 * @param string $option    contains the information of option to run
3599
 * @param int    $user_id   contains the information the current user id
3600
 * @param int    $thread_id contains the information the current thread id
3601
 *
3602
 * @return int qualify
3603
 *             <code> $option=1 obtained the qualification of the current thread</code>
3604
 *
3605
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3606
 *
3607
 * @version October 2008, dokeos  1.8.6
3608
 */
3609
function showQualify($option, $user_id, $thread_id)
3610
{
3611
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3612
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3613
3614
    $course_id = api_get_course_int_id();
3615
    $user_id = (int) $user_id;
3616
    $thread_id = (int) $thread_id;
3617
3618
    if (empty($user_id) || empty($thread_id)) {
3619
        return false;
3620
    }
3621
3622
    $sql = '';
3623
    switch ($option) {
3624
        case 1:
3625
            $sql = "SELECT qualify FROM $table_threads_qualify
3626
                    WHERE
3627
                        c_id = $course_id AND
3628
                        user_id=".$user_id." AND
3629
                        thread_id=".$thread_id;
3630
            break;
3631
        case 2:
3632
            $sql = "SELECT thread_qualify_max FROM $table_threads
3633
                    WHERE c_id = $course_id AND thread_id=".$thread_id;
3634
            break;
3635
    }
3636
3637
    if (!empty($sql)) {
3638
        $rs = Database::query($sql);
3639
        $row = Database::fetch_array($rs);
3640
3641
        return $row[0];
3642
    }
3643
3644
    return [];
3645
}
3646
3647
/**
3648
 * This function gets qualify historical.
3649
 *
3650
 * @param int  $user_id   contains the information the current user id
3651
 * @param int  $thread_id contains the information the current thread id
3652
 * @param bool $opt       contains the information of option to run
3653
 *
3654
 * @return array
3655
 *
3656
 * @author Christian Fasanando <[email protected]>,
3657
 * @author Isaac Flores <[email protected]>,
3658
 *
3659
 * @version October 2008, dokeos  1.8.6
3660
 */
3661
function getThreadScoreHistory($user_id, $thread_id, $opt)
3662
{
3663
    $user_id = (int) $user_id;
3664
    $thread_id = (int) $thread_id;
3665
3666
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3667
    $course_id = api_get_course_int_id();
3668
3669
    if ($opt == 'false') {
3670
        $sql = "SELECT * FROM $table_threads_qualify_log
3671
                WHERE
3672
                    c_id = $course_id AND
3673
                    thread_id='".$thread_id."' AND
3674
                    user_id='".$user_id."'
3675
                ORDER BY qualify_time";
3676
    } else {
3677
        $sql = "SELECT * FROM $table_threads_qualify_log
3678
                WHERE
3679
                    c_id = $course_id AND
3680
                    thread_id='".$thread_id."' AND
3681
                    user_id='".$user_id."'
3682
                ORDER BY qualify_time DESC";
3683
    }
3684
    $rs = Database::query($sql);
3685
    $log = [];
3686
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3687
        $log[] = $row;
3688
    }
3689
3690
    return $log;
3691
}
3692
3693
/**
3694
 * This function stores qualify historical.
3695
 *
3696
 * @param bool contains the information of option to run
3697
 * @param string contains the information the current course id
3698
 * @param int contains the information the current forum id
3699
 * @param int contains the information the current user id
3700
 * @param int contains the information the current thread id
3701
 * @param int contains the information the current qualify
3702
 * @param string $option
3703
 * @param int    $course_id
3704
 * @param int    $user_id
3705
 * @param int    $thread_id
3706
 *
3707
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3708
 *
3709
 * @version October 2008, dokeos  1.8.6
3710
 */
3711
function saveThreadScoreHistory(
3712
    $option,
3713
    $course_id,
3714
    $user_id,
3715
    $thread_id
3716
) {
3717
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3718
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3719
3720
    $thread_id = (int) $thread_id;
3721
    $course_id = (int) $course_id;
3722
    $user_id = (int) $user_id;
3723
    $qualify_user_id = api_get_user_id();
3724
3725
    if ($user_id == strval(intval($user_id)) &&
3726
        $thread_id == strval(intval($thread_id)) && $option == 1
3727
    ) {
3728
        // Extract information of thread_qualify.
3729
        $sql = "SELECT qualify, qualify_time
3730
                FROM $table_threads_qualify
3731
                WHERE
3732
                    c_id = $course_id AND
3733
                    user_id = ".$user_id." AND
3734
                    thread_id = ".$thread_id." AND
3735
                    qualify_user_id = $qualify_user_id
3736
                ";
3737
        $rs = Database::query($sql);
3738
        $row = Database::fetch_array($rs);
3739
3740
        // Insert thread_historical.
3741
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3742
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3743
        Database::query($sql);
3744
3745
        $insertId = Database::insert_id();
3746
        if ($insertId) {
3747
            $sql = "UPDATE $table_threads_qualify_log SET id = iid
3748
                    WHERE iid = $insertId";
3749
            Database::query($sql);
3750
        }
3751
    }
3752
}
3753
3754
/**
3755
 * This function shows current thread qualify .
3756
 *
3757
 * @param int $threadId
3758
 * @param int $sessionId
3759
 * @param int $userId
3760
 *
3761
 * @return array or null if is empty
3762
 *
3763
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3764
 *
3765
 * @version December 2008, dokeos  1.8.6
3766
 */
3767
function current_qualify_of_thread($threadId, $sessionId, $userId)
3768
{
3769
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3770
3771
    $course_id = api_get_course_int_id();
3772
    $currentUserId = api_get_user_id();
3773
    $sessionId = intval($sessionId);
3774
    $threadId = intval($threadId);
3775
3776
    $sql = "SELECT qualify FROM $table_threads_qualify
3777
            WHERE
3778
                c_id = $course_id AND
3779
                thread_id = $threadId AND
3780
                session_id = $sessionId AND
3781
                qualify_user_id = $currentUserId AND
3782
                user_id = $userId
3783
            ";
3784
    $res = Database::query($sql);
3785
    $row = Database::fetch_array($res, 'ASSOC');
3786
3787
    return $row['qualify'];
3788
}
3789
3790
/**
3791
 * This function stores a reply in the forum_post table.
3792
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date).
3793
 *
3794
 * @param array $current_forum
3795
 * @param array $values
3796
 * @param int   $courseId      Optional
3797
 * @param int   $userId        Optional
3798
 *
3799
 * @return int post id
3800
 *
3801
 * @author Patrick Cool <[email protected]>, Ghent University
3802
 *
3803
 * @version february 2006, dokeos 1.8
3804
 */
3805
function store_reply($current_forum, $values, $courseId = 0, $userId = 0)
3806
{
3807
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
3808
    $_course = api_get_course_info_by_id($courseId);
3809
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3810
    $post_date = api_get_utc_datetime();
3811
    $userId = $userId ?: api_get_user_id();
3812
3813
    if ($current_forum['allow_anonymous'] == 1) {
3814
        if (api_is_anonymous() && empty($userId)) {
3815
            $userId = api_get_anonymous_id();
3816
        }
3817
    }
3818
3819
    if (empty($userId)) {
3820
        return false;
3821
    }
3822
3823
    $visible = 1;
3824
    if ($current_forum['approval_direct_post'] == '1' &&
3825
        !api_is_allowed_to_edit(null, true)
3826
    ) {
3827
        $visible = 0;
3828
    }
3829
3830
    $upload_ok = 1;
3831
    $new_post_id = 0;
3832
3833
    if ($upload_ok) {
3834
        // We first store an entry in the forum_post table.
3835
        $new_post_id = Database::insert(
3836
            $table_posts,
3837
            [
3838
                'c_id' => $courseId,
3839
                'post_title' => $values['post_title'],
3840
                'post_text' => isset($values['post_text']) ? ($values['post_text']) : null,
3841
                'thread_id' => $values['thread_id'],
3842
                'forum_id' => $values['forum_id'],
3843
                'poster_id' => $userId,
3844
                'post_id' => 0,
3845
                'post_date' => $post_date,
3846
                'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : null,
3847
                'post_parent_id' => isset($values['post_parent_id']) ? $values['post_parent_id'] : null,
3848
                'visible' => $visible,
3849
            ]
3850
        );
3851
3852
        if ($new_post_id) {
3853
            $sql = "UPDATE $table_posts SET post_id = iid WHERE iid = $new_post_id";
3854
            Database::query($sql);
3855
3856
            $values['new_post_id'] = $new_post_id;
3857
            $message = get_lang('ReplyAdded');
3858
3859
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3860
                foreach ($_POST['file_ids'] as $key => $id) {
3861
                    editAttachedFile(
3862
                        [
3863
                            'comment' => $_POST['file_comments'][$key],
3864
                            'post_id' => $new_post_id,
3865
                        ],
3866
                        $id
3867
                    );
3868
                }
3869
            }
3870
3871
            // Update the thread.
3872
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
3873
3874
            // Update the forum.
3875
            api_item_property_update(
3876
                $_course,
3877
                TOOL_FORUM,
3878
                $values['forum_id'],
3879
                'NewMessageInForum',
3880
                $userId
3881
            );
3882
3883
            // Insert post
3884
            api_item_property_update(
3885
                $_course,
3886
                TOOL_FORUM_POST,
3887
                $new_post_id,
3888
                'NewPost',
3889
                $userId
3890
            );
3891
3892
            if ($current_forum['approval_direct_post'] == '1' &&
3893
                !api_is_allowed_to_edit(null, true)
3894
            ) {
3895
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3896
            }
3897
3898
            if ($current_forum['moderated'] &&
3899
                !api_is_allowed_to_edit(null, true)
3900
            ) {
3901
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3902
            }
3903
3904
            // Setting the notification correctly.
3905
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3906
            if ($my_post_notification == 1) {
3907
                set_notification('thread', $values['thread_id'], true);
3908
            }
3909
3910
            send_notification_mails(
3911
                $values['forum_id'],
3912
                $values['thread_id'],
3913
                $values
3914
            );
3915
            add_forum_attachment_file('', $new_post_id);
3916
3917
            $logInfo = [
3918
                'tool' => TOOL_FORUM,
3919
                'tool_id' => $values['forum_id'],
3920
                'tool_id_detail' => $values['thread_id'],
3921
                'action' => 'new-post',
3922
                'action_details' => $values['action'],
3923
                'info' => $values['post_title'],
3924
            ];
3925
            Event::registerLog($logInfo);
3926
        }
3927
3928
        Session::erase('formelements');
3929
        Session::erase('origin');
3930
        Session::erase('breadcrumbs');
3931
        Session::erase('addedresource');
3932
        Session::erase('addedresourceid');
3933
3934
        Display::addFlash(Display::return_message($message, 'confirmation', false));
3935
    } else {
3936
        Display::addFlash(
3937
            Display::return_message(
3938
                get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst'),
3939
                'error'
3940
            )
3941
        );
3942
    }
3943
3944
    return $new_post_id;
3945
}
3946
3947
/**
3948
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
3949
 *
3950
 * @param array contains all the information about the current post
3951
 * @param array contains all the information about the current thread
3952
 * @param array contains all info about the current forum (to check if attachments are allowed)
3953
 * @param array contains the default values to fill the form
3954
 *
3955
 * @author Patrick Cool <[email protected]>, Ghent University
3956
 *
3957
 * @version february 2006, dokeos 1.8
3958
 */
3959
function show_edit_post_form(
3960
    $current_post,
3961
    $current_thread,
3962
    $current_forum,
3963
    $form_values = '',
3964
    $id_attach = 0
3965
) {
3966
    // Initialize the object.
3967
    $form = new FormValidator(
3968
        'edit_post',
3969
        'post',
3970
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.intval($_GET['post'])
3971
    );
3972
    $form->addElement('header', get_lang('EditPost'));
3973
    // Setting the form elements.
3974
    $form->addElement('hidden', 'post_id', $current_post['post_id']);
3975
    $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
3976
    $form->addElement('hidden', 'id_attach', $id_attach);
3977
3978
    if (empty($current_post['post_parent_id'])) {
3979
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
3980
    }
3981
3982
    $form->addElement('text', 'post_title', get_lang('Title'));
3983
    $form->applyFilter('post_title', 'html_filter');
3984
    $form->addElement(
3985
        'html_editor',
3986
        'post_text',
3987
        get_lang('Text'),
3988
        null,
3989
        api_is_allowed_to_edit(null, true) ? [
3990
            'ToolbarSet' => 'Forum',
3991
            'Width' => '100%',
3992
            'Height' => '400',
3993
        ] : [
3994
            'ToolbarSet' => 'ForumStudent',
3995
            'Width' => '100%',
3996
            'Height' => '400',
3997
            'UserStatus' => 'student',
3998
        ]
3999
    );
4000
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
4001
4002
    $extraFields = new ExtraField('forum_post');
4003
    $extraFields->addElements($form, $current_post['post_id']);
4004
4005
    $form->addButtonAdvancedSettings('advanced_params');
4006
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
4007
4008
    if ($current_forum['moderated'] && api_is_allowed_to_edit(null, true)) {
4009
        $group = [];
4010
        $group[] = $form->createElement(
4011
            'radio',
4012
            'status',
4013
            null,
4014
            get_lang('Validated'),
4015
            1
4016
        );
4017
        $group[] = $form->createElement(
4018
            'radio',
4019
            'status',
4020
            null,
4021
            get_lang('WaitingModeration'),
4022
            2
4023
        );
4024
        $group[] = $form->createElement(
4025
            'radio',
4026
            'status',
4027
            null,
4028
            get_lang('Rejected'),
4029
            3
4030
        );
4031
        $form->addGroup($group, 'status', get_lang('Status'));
4032
    }
4033
4034
    $defaults['status']['status'] = isset($current_post['status']) && !empty($current_post['status']) ? $current_post['status'] : 2;
4035
    $form->addElement(
4036
        'checkbox',
4037
        'post_notification',
4038
        '',
4039
        get_lang('NotifyByEmail').' ('.$current_post['email'].')'
4040
    );
4041
4042
    if (api_is_allowed_to_edit(null, true) &&
4043
        empty($current_post['post_parent_id'])
4044
    ) {
4045
        // The sticky checkbox only appears when it is the first post of a thread.
4046
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
4047
        if ($current_thread['thread_sticky'] == 1) {
4048
            $defaults['thread_sticky'] = true;
4049
        }
4050
    }
4051
4052
    $form->addElement('html', '</div>');
4053
4054
    $form->addFile('user_upload[]', get_lang('Attachment'));
4055
    $form->addButton(
4056
        'add_attachment',
4057
        get_lang('AddAttachment'),
4058
        'paperclip',
4059
        'default',
4060
        'default',
4061
        null,
4062
        ['id' => 'reply-add-attachment']
4063
    );
4064
4065
    $form->addButtonUpdate(get_lang('Modify'), 'SubmitPost');
4066
4067
    // Setting the default values for the form elements.
4068
    $defaults['post_title'] = $current_post['post_title'];
4069
    $defaults['post_text'] = $current_post['post_text'];
4070
4071
    if ($current_post['post_notification'] == 1) {
4072
        $defaults['post_notification'] = true;
4073
    }
4074
4075
    if (!empty($form_values)) {
4076
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
4077
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
4078
    }
4079
4080
    $form->setDefaults($defaults);
4081
4082
    // The course admin can make a thread sticky (=appears with special icon and always on top).
4083
4084
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
4085
4086
    // Validation or display
4087
    if ($form->validate()) {
4088
        $values = $form->exportValues();
4089
4090
        $values['item_id'] = $current_post['post_id'];
4091
        $extraFieldValues = new ExtraFieldValue('forum_post');
4092
        $extraFieldValues->saveFieldValues($values);
4093
4094
        store_edit_post($current_forum, $values);
4095
    } else {
4096
        // Delete from $_SESSION forum attachment from other posts
4097
        clearAttachedFiles($current_post['post_id']);
4098
        // Get forum attachment ajax table to add it to form
4099
        $fileData = getAttachmentsAjaxTable($current_post['post_id'], $current_forum['forum_id']);
4100
        $form->addElement('html', $fileData);
4101
        $form->display();
4102
    }
4103
}
4104
4105
/**
4106
 * This function stores the edit of a post in the forum_post table.
4107
 *
4108
 * @param array
4109
 *
4110
 * @author Patrick Cool <[email protected]>, Ghent University
4111
 *
4112
 * @version february 2006, dokeos 1.8
4113
 */
4114
function store_edit_post($forumInfo, $values)
4115
{
4116
    $logInfo = [
4117
        'tool' => TOOL_FORUM,
4118
        'tool_id' => $_GET['forum'],
4119
        'tool_id_detail' => $values['thread_id'],
4120
        'action' => 'edit-post',
4121
        'action_details' => 'post',
4122
        'info' => $values['post_title'],
4123
    ];
4124
    Event::registerLog($logInfo);
4125
4126
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
4127
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4128
    $course_id = api_get_course_int_id();
4129
4130
    //check if this post is the first of the thread
4131
    // First we check if the change affects the thread and if so we commit
4132
    // the changes (sticky and post_title=thread_title are relevant).
4133
4134
    $posts = getPosts($forumInfo, $values['thread_id']);
4135
    $first_post = null;
4136
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
4137
        $first_post = $posts[0];
4138
    }
4139
4140
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
4141
        // Simple edit
4142
        $params = [
4143
            'thread_title' => $values['post_title'],
4144
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
4145
        ];
4146
        $where = ['c_id = ? AND thread_id = ?' => [$course_id, $values['thread_id']]];
4147
        Database::update($threadTable, $params, $where);
4148
    }
4149
4150
    $status = '';
4151
    $updateStatus = false;
4152
    if ($forumInfo['moderated']) {
4153
        if (api_is_allowed_to_edit(null, true)) {
4154
            $status = $values['status']['status'];
4155
            $updateStatus = true;
4156
        } else {
4157
            $status = CForumPost::STATUS_WAITING_MODERATION;
4158
            $updateStatus = true;
4159
        }
4160
    }
4161
4162
    // Update the post_title and the post_text.
4163
    $params = [
4164
        'post_title' => $values['post_title'],
4165
        'post_text' => $values['post_text'],
4166
        'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : '',
4167
    ];
4168
4169
    if ($updateStatus) {
4170
        $params['status'] = $status;
4171
    }
4172
4173
    $where = ['c_id = ? AND post_id = ?' => [$course_id, $values['post_id']]];
4174
    Database::update($table_posts, $params, $where);
4175
4176
    // Update attached files
4177
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
4178
        foreach ($_POST['file_ids'] as $key => $id) {
4179
            editAttachedFile(
4180
                [
4181
                    'comment' => $_POST['file_comments'][$key],
4182
                    'post_id' => $values['post_id'],
4183
                ],
4184
                $id
4185
            );
4186
        }
4187
    }
4188
4189
    if (!empty($values['remove_attach'])) {
4190
        delete_attachment($values['post_id']);
4191
    }
4192
4193
    if (empty($values['id_attach'])) {
4194
        add_forum_attachment_file(
4195
            isset($values['file_comment']) ? $values['file_comment'] : null,
4196
            $values['post_id']
4197
        );
4198
    } else {
4199
        edit_forum_attachment_file(
4200
            isset($values['file_comment']) ? $values['file_comment'] : null,
4201
            $values['post_id'],
4202
            $values['id_attach']
4203
        );
4204
    }
4205
4206
    $message = get_lang('EditPostStored').'<br />';
4207
    $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&">'.get_lang('Forum').'</a><br />';
4208
    $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>';
4209
4210
    Session::erase('formelements');
4211
    Session::erase('origin');
4212
    Session::erase('breadcrumbs');
4213
    Session::erase('addedresource');
4214
    Session::erase('addedresourceid');
4215
4216
    echo Display::return_message($message, 'confirmation', false);
4217
}
4218
4219
/**
4220
 * This function displays the firstname and lastname of the user as a link to the user tool.
4221
 *
4222
 * @param string names
4223
 * @ in_title : title tootip
4224
 *
4225
 * @return string HTML
4226
 *
4227
 * @author Patrick Cool <[email protected]>, Ghent University
4228
 *
4229
 * @version february 2006, dokeos 1.8
4230
 */
4231
function display_user_link($user_id, $name, $origin = '', $in_title = '')
4232
{
4233
    if ($user_id != 0) {
4234
        $userInfo = api_get_user_info($user_id);
4235
4236
        return '<a href="'.$userInfo['profile_url'].'">'.Security::remove_XSS($userInfo['complete_name']).'</a>';
4237
    } else {
4238
        return $name.' ('.get_lang('Anonymous').')';
4239
    }
4240
}
4241
4242
/**
4243
 * This function displays the user image from the profile, with a link to the user's details.
4244
 *
4245
 * @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...
4246
 * @param   string  User's name
4247
 * @param   string  the origin where the forum is called (example : learnpath)
4248
 *
4249
 * @return string An HTML with the anchor and the image of the user
4250
 *
4251
 * @author Julio Montoya <[email protected]>
4252
 */
4253
function display_user_image($user_id, $name, $origin = '')
4254
{
4255
    $userInfo = api_get_user_info($user_id);
4256
    $link = '<a href="'.(!empty($origin) ? '#' : $userInfo['profile_url']).'" '.(!empty($origin) ? 'target="_self"' : '').'>';
4257
4258
    if ($user_id != 0) {
4259
        return $link.'<img src="'.$userInfo['avatar'].'"  alt="'.$name.'"  title="'.$name.'" /></a>';
4260
    } else {
4261
        return $link.Display::return_icon('unknown.jpg', $name).'</a>';
4262
    }
4263
}
4264
4265
/**
4266
 * The thread view counter gets increased every time someone looks at the thread.
4267
 *
4268
 * @param int
4269
 *
4270
 * @author Patrick Cool <[email protected]>, Ghent University
4271
 *
4272
 * @version february 2006, dokeos 1.8
4273
 */
4274
function increase_thread_view($thread_id)
4275
{
4276
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4277
    $course_id = api_get_course_int_id();
4278
4279
    $sql = "UPDATE $table_threads 
4280
            SET thread_views = thread_views + 1
4281
            WHERE 
4282
                c_id = $course_id AND  
4283
                thread_id = '".intval($thread_id)."'";
4284
    Database::query($sql);
4285
}
4286
4287
/**
4288
 * The relies counter gets increased every time somebody replies to the thread.
4289
 *
4290
 * @author Patrick Cool <[email protected]>, Ghent University
4291
 *
4292
 * @version february 2006, dokeos 1.8
4293
 *
4294
 * @param int    $threadId
4295
 * @param string $lastPostId
4296
 * @param string $post_date
4297
 */
4298
function updateThreadInfo($threadId, $lastPostId, $post_date)
4299
{
4300
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4301
    $course_id = api_get_course_int_id();
4302
    $sql = "UPDATE $table_threads SET 
4303
            thread_replies = thread_replies+1,
4304
            thread_last_post = '".Database::escape_string($lastPostId)."',
4305
            thread_date = '".Database::escape_string($post_date)."'
4306
            WHERE 
4307
                c_id = $course_id AND  
4308
                thread_id='".Database::escape_string($threadId)."'"; // this needs to be cleaned first
4309
    Database::query($sql);
4310
}
4311
4312
/**
4313
 * This function is used to find all the information about what's new in the forum tool.
4314
 *
4315
 * @author Patrick Cool <[email protected]>, Ghent University
4316
 *
4317
 * @version february 2006, dokeos 1.8
4318
 */
4319
function get_whats_new()
4320
{
4321
    $userId = api_get_user_id();
4322
    $course_id = api_get_course_int_id();
4323
4324
    if (empty($course_id) || empty($userId)) {
4325
        return false;
4326
    }
4327
4328
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4329
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
4330
4331
    $tool = TOOL_FORUM;
4332
    $lastForumAccess = Session::read('last_forum_access');
4333
4334
    if (!$lastForumAccess) {
4335
        $sql = "SELECT * FROM $tracking_last_tool_access
4336
                WHERE
4337
                    access_user_id = $userId AND
4338
                    c_id = $course_id AND
4339
                    access_tool = '".Database::escape_string($tool)."'";
4340
        $result = Database::query($sql);
4341
        $row = Database::fetch_array($result);
4342
        if (isset($row['access_date'])) {
4343
            Session::write('last_forum_access', $row['access_date']);
4344
            $lastForumAccess = $row['access_date'];
4345
        }
4346
    }
4347
4348
    $whatsNew = Session::read('whatsnew_post_info');
4349
4350
    if (!$whatsNew) {
4351
        if ($lastForumAccess != '') {
4352
            $postInfo = [];
4353
            $sql = "SELECT * FROM $table_posts
4354
                    WHERE
4355
                        c_id = $course_id AND
4356
                        visible = 1 AND                        
4357
                        post_date > '".Database::escape_string($lastForumAccess)."'";
4358
            $result = Database::query($sql);
4359
            while ($row = Database::fetch_array($result)) {
4360
                $postInfo[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
4361
            }
4362
            Session::write('whatsnew_post_info', $postInfo);
4363
        }
4364
    }
4365
}
4366
4367
/**
4368
 * This function approves a post = change.
4369
 *
4370
 * @param int    $post_id the id of the post that will be deleted
4371
 * @param string $action  make the post visible or invisible
4372
 *
4373
 * @return string language variable
4374
 *
4375
 * @author Patrick Cool <[email protected]>, Ghent University
4376
 *
4377
 * @version february 2006, dokeos 1.8
4378
 */
4379
function approve_post($post_id, $action)
4380
{
4381
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4382
    $course_id = api_get_course_int_id();
4383
4384
    if ($action == 'invisible') {
4385
        $visibility_value = 0;
4386
    }
4387
4388
    if ($action == 'visible') {
4389
        $visibility_value = 1;
4390
        handle_mail_cue('post', $post_id);
4391
    }
4392
4393
    $sql = "UPDATE $table_posts SET
4394
            visible='".Database::escape_string($visibility_value)."'
4395
            WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
4396
    $return = Database::query($sql);
4397
4398
    if ($return) {
4399
        return 'PostVisibilityChanged';
4400
    }
4401
}
4402
4403
/**
4404
 * This function retrieves all the unapproved messages for a given forum
4405
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this).
4406
 *
4407
 * @param $forum_id the forum where we want to know the unapproved messages of
4408
 *
4409
 * @return array returns
4410
 *
4411
 * @author Patrick Cool <[email protected]>, Ghent University
4412
 *
4413
 * @version february 2006, dokeos 1.8
4414
 */
4415
function get_unaproved_messages($forum_id)
4416
{
4417
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4418
    $course_id = api_get_course_int_id();
4419
4420
    $return_array = [];
4421
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
4422
            WHERE 
4423
                c_id = $course_id AND 
4424
                forum_id='".Database::escape_string($forum_id)."' AND 
4425
                visible='0' ";
4426
    $result = Database::query($sql);
4427
    while ($row = Database::fetch_array($result)) {
4428
        $return_array[] = $row['thread_id'];
4429
    }
4430
4431
    return $return_array;
4432
}
4433
4434
/**
4435
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
4436
 * was added to a given thread.
4437
 *
4438
 * @param array reply information
4439
 *
4440
 * @author Patrick Cool <[email protected]>, Ghent University
4441
 *
4442
 * @version february 2006, dokeos 1.8
4443
 */
4444
function send_notification_mails($forumId, $thread_id, $reply_info)
4445
{
4446
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4447
4448
    // First we need to check if
4449
    // 1. the forum category is visible
4450
    // 2. the forum is visible
4451
    // 3. the thread is visible
4452
    // 4. the reply is visible (=when there is)
4453
    $current_thread = get_thread_information($forumId, $thread_id);
4454
    $current_forum = get_forum_information($current_thread['forum_id'], $current_thread['c_id']);
4455
4456
    $current_forum_category = null;
4457
    if (isset($current_forum['forum_category'])) {
4458
        $current_forum_category = get_forumcategory_information($current_forum['forum_category']);
4459
    }
4460
4461
    $send_mails = false;
4462
    if ($current_thread['visibility'] == '1' &&
4463
        $current_forum['visibility'] == '1' &&
4464
        ($current_forum_category && $current_forum_category['visibility'] == '1') &&
4465
        $current_forum['approval_direct_post'] != '1'
4466
    ) {
4467
        $send_mails = true;
4468
    }
4469
4470
    // The forum category, the forum, the thread and the reply are visible to the user
4471
    if ($send_mails && !empty($forumId)) {
4472
        $postId = isset($reply_info['new_post_id']) ? $reply_info['new_post_id'] : 0;
4473
        send_notifications($forumId, $thread_id, $postId);
4474
    } else {
4475
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
4476
        if (isset($current_forum['forum_id'])) {
4477
            $sql = "SELECT * FROM $table_notification
4478
                    WHERE
4479
                        c_id = ".api_get_course_int_id()." AND
4480
                        (
4481
                            forum_id = '".intval($current_forum['forum_id'])."' OR
4482
                            thread_id = '".intval($thread_id)."'
4483
                        ) ";
4484
4485
            $result = Database::query($sql);
4486
            $user_id = api_get_user_id();
4487
            while ($row = Database::fetch_array($result)) {
4488
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
4489
                        VALUES (".api_get_course_int_id().", '".intval($thread_id)."', '".intval($reply_info['new_post_id'])."', '$user_id' )";
4490
                Database::query($sql);
4491
            }
4492
        }
4493
    }
4494
}
4495
4496
/**
4497
 * This function is called whenever something is made visible because there might
4498
 * be new posts and the user might have indicated that (s)he wanted to be
4499
 * informed about the new posts by mail.
4500
 *
4501
 * @param string $content Content type (post, thread, forum, forum_category)
4502
 * @param int    $id      Item DB ID of the corresponding content type
4503
 *
4504
 * @return string language variable
4505
 *
4506
 * @author Patrick Cool <[email protected]>, Ghent University
4507
 *
4508
 * @version february 2006, dokeos 1.8
4509
 */
4510
function handle_mail_cue($content, $id)
4511
{
4512
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4513
    $table_forums = Database::get_course_table(TABLE_FORUM);
4514
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4515
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4516
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4517
4518
    $course_id = api_get_course_int_id();
4519
    $id = (int) $id;
4520
4521
    /* If the post is made visible we only have to send mails to the people
4522
     who indicated that they wanted to be informed for that thread.*/
4523
    if ($content == 'post') {
4524
        // Getting the information about the post (need the thread_id).
4525
        $post_info = get_post_information($id);
4526
        $thread_id = (int) $post_info['thread_id'];
4527
4528
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4529
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
4530
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4531
                WHERE
4532
                    posts.c_id = $course_id AND
4533
                    mailcue.c_id = $course_id AND
4534
                    posts.thread_id = $thread_id AND
4535
                    posts.post_notification = '1' AND
4536
                    mailcue.thread_id = $thread_id AND
4537
                    users.user_id = posts.poster_id AND
4538
                    users.active = 1
4539
                GROUP BY users.email";
4540
4541
        $result = Database::query($sql);
4542
        while ($row = Database::fetch_array($result)) {
4543
            $forumInfo = get_forum_information($post_info['forum_id']);
4544
            send_mail($row, $forumInfo, get_thread_information($post_info['forum_id'], $post_info['thread_id']), $post_info);
4545
        }
4546
    } elseif ($content == 'thread') {
4547
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4548
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email, posts.forum_id
4549
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4550
                WHERE
4551
                    posts.c_id = $course_id AND
4552
                    mailcue.c_id = $course_id AND
4553
                    posts.thread_id = $id AND
4554
                    posts.post_notification = '1' AND
4555
                    mailcue.thread_id = $id AND
4556
                    users.user_id = posts.poster_id AND
4557
                    users.active = 1
4558
                GROUP BY users.email";
4559
        $result = Database::query($sql);
4560
        while ($row = Database::fetch_array($result)) {
4561
            $forumInfo = get_forum_information($row['forum_id']);
4562
            send_mail($row, $forumInfo, get_thread_information($row['forum_id'], $id));
4563
        }
4564
4565
        // Deleting the relevant entries from the mailcue.
4566
        $sql = "DELETE FROM $table_mailcue
4567
                WHERE c_id = $course_id AND thread_id = $id";
4568
        Database::query($sql);
4569
    } elseif ($content == 'forum') {
4570
        $sql = "SELECT thread_id FROM $table_threads
4571
                WHERE c_id = $course_id AND forum_id = $id";
4572
        $result = Database::query($sql);
4573
        while ($row = Database::fetch_array($result)) {
4574
            handle_mail_cue('thread', $row['thread_id']);
4575
        }
4576
    } elseif ($content == 'forum_category') {
4577
        $sql = "SELECT forum_id FROM $table_forums
4578
                WHERE c_id = $course_id AND forum_category = $id";
4579
        $result = Database::query($sql);
4580
        while ($row = Database::fetch_array($result)) {
4581
            handle_mail_cue('forum', $row['forum_id']);
4582
        }
4583
    } else {
4584
        return get_lang('Error');
4585
    }
4586
}
4587
4588
/**
4589
 * This function sends the mails for the mail notification.
4590
 *
4591
 * @param array
4592
 * @param array
4593
 * @param array
4594
 * @param array
4595
 *
4596
 * @author Patrick Cool <[email protected]>, Ghent University
4597
 *
4598
 * @version february 2006, dokeos 1.8
4599
 */
4600
function send_mail($userInfo, $forumInfo, $thread_information, $postInfo = [])
4601
{
4602
    if (empty($userInfo) || empty($forumInfo) || empty($thread_information)) {
4603
        return false;
4604
    }
4605
4606
    $_course = api_get_course_info();
4607
    $user_id = api_get_user_id();
4608
4609
    $thread_link = '';
4610
    if (isset($thread_information) && is_array($thread_information)) {
4611
        $thread_link = api_get_path(WEB_CODE_PATH).
4612
            'forum/viewthread.php?'.api_get_cidreq().'&forum='.$thread_information['forum_id'].'&thread='.$thread_information['thread_id'];
4613
    }
4614
    $email_body = get_lang('Dear').' '.api_get_person_name($userInfo['firstname'], $userInfo['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4615
    $email_body .= get_lang('NewForumPost').': '.$forumInfo['forum_title'].' - '.$thread_information['thread_title']." <br />\n";
4616
4617
    $courseId = api_get_configuration_value('global_forums_course_id');
4618
    $subject = get_lang('NewForumPost').' - '.$_course['official_code'].': '.$forumInfo['forum_title'].' - '.$thread_information['thread_title']." <br />\n";
4619
4620
    $courseInfoTitle = get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4621
    if (!empty($courseId) && $_course['real_id'] == $courseId) {
4622
        $subject = get_lang('NewForumPost').': '.$forumInfo['forum_title'].' - '.$thread_information['thread_title']." <br />\n";
4623
        $courseInfoTitle = " <br />\n";
4624
    }
4625
    $email_body .= $courseInfoTitle;
4626
4627
    if (!empty($postInfo) && isset($postInfo['post_text'])) {
4628
        $text = cut(strip_tags($postInfo['post_text']), 100);
4629
        if (!empty($text)) {
4630
            $email_body .= get_lang('Message').": <br />\n ";
4631
            $email_body .= $text;
4632
            $email_body .= "<br /><br />\n";
4633
        }
4634
    }
4635
4636
    $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
4637
4638
    if (!empty($thread_link)) {
4639
        $email_body .= get_lang('ThreadCanBeFoundHere')." : <br /><a href=\"".$thread_link."\">".$thread_link."</a>\n";
4640
    }
4641
4642
    if ($userInfo['user_id'] != $user_id) {
4643
        MessageManager::send_message(
4644
            $userInfo['user_id'],
4645
            $subject,
4646
            $email_body,
4647
            [],
4648
            [],
4649
            null,
4650
            null,
4651
            null,
4652
            null,
4653
            $user_id
4654
        );
4655
    }
4656
}
4657
4658
/**
4659
 * This function displays the form for moving a thread to a different (already existing) forum.
4660
 *
4661
 * @author Patrick Cool <[email protected]>, Ghent University
4662
 *
4663
 * @version february 2006, dokeos 1.8
4664
 */
4665
function move_thread_form()
4666
{
4667
    $form = new FormValidator(
4668
        'movepost',
4669
        'post',
4670
        api_get_self().'?forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4671
    );
4672
    // The header for the form
4673
    $form->addElement('header', get_lang('MoveThread'));
4674
    // Invisible form: the thread_id
4675
    $form->addElement('hidden', 'thread_id', intval($_GET['thread']));
4676
    // the fora
4677
    $forum_categories = get_forum_categories();
4678
    $forums = get_forums();
4679
4680
    $htmlcontent = '<div class="row">
4681
        <div class="label">
4682
            <span class="form_required">*</span>'.get_lang('MoveTo').'
4683
        </div>
4684
        <div class="formw">';
4685
    $htmlcontent .= '<select name="forum">';
4686
    foreach ($forum_categories as $key => $category) {
4687
        $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
4688
        foreach ($forums as $key => $forum) {
4689
            if (isset($forum['forum_category'])) {
4690
                if ($forum['forum_category'] == $category['cat_id']) {
4691
                    $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
4692
                }
4693
            }
4694
        }
4695
        $htmlcontent .= '</optgroup>';
4696
    }
4697
    $htmlcontent .= "</select>";
4698
    $htmlcontent .= '   </div>
4699
                    </div>';
4700
4701
    $form->addElement('html', $htmlcontent);
4702
4703
    // The OK button
4704
    $form->addButtonSave(get_lang('MoveThread'), 'SubmitForum');
4705
4706
    // Validation or display
4707
    if ($form->validate()) {
4708
        $values = $form->exportValues();
4709
        if (isset($_POST['forum'])) {
4710
            store_move_thread($values);
4711
        }
4712
    } else {
4713
        $form->display();
4714
    }
4715
}
4716
4717
/**
4718
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4719
 *
4720
 * @author Patrick Cool <[email protected]>, Ghent University
4721
 *
4722
 * @version february 2006, dokeos 1.8
4723
 */
4724
function move_post_form()
4725
{
4726
    $form = new FormValidator(
4727
        'movepost',
4728
        'post',
4729
        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'])
4730
    );
4731
    // The header for the form
4732
    $form->addElement('header', '', get_lang('MovePost'));
4733
4734
    // Invisible form: the post_id
4735
    $form->addElement('hidden', 'post_id', intval($_GET['post']));
4736
4737
    // Dropdown list: Threads of this forum
4738
    $threads = get_threads($_GET['forum']);
4739
    //my_print_r($threads);
4740
    $threads_list[0] = get_lang('ANewThread');
4741
    foreach ($threads as $key => $value) {
4742
        $threads_list[$value['thread_id']] = $value['thread_title'];
4743
    }
4744
    $form->addElement('select', 'thread', get_lang('MoveToThread'), $threads_list);
4745
    $form->applyFilter('thread', 'html_filter');
4746
4747
    // The OK button
4748
    $form->addButtonSave(get_lang('MovePost'), 'submit');
4749
4750
    // Setting the rules
4751
    $form->addRule('thread', get_lang('ThisFieldIsRequired'), 'required');
4752
4753
    // Validation or display
4754
    if ($form->validate()) {
4755
        $values = $form->exportValues();
4756
        store_move_post($values);
4757
    } else {
4758
        $form->display();
4759
    }
4760
}
4761
4762
/**
4763
 * @param array
4764
 *
4765
 * @return string HTML language variable
4766
 *
4767
 * @author Patrick Cool <[email protected]>, Ghent University
4768
 *
4769
 * @version february 2006, dokeos 1.8
4770
 */
4771
function store_move_post($values)
4772
{
4773
    $_course = api_get_course_info();
4774
    $course_id = api_get_course_int_id();
4775
4776
    $table_forums = Database::get_course_table(TABLE_FORUM);
4777
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4778
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4779
4780
    if ($values['thread'] == '0') {
4781
        $current_post = get_post_information($values['post_id']);
4782
4783
        // Storing a new thread.
4784
        $params = [
4785
            'c_id' => $course_id,
4786
            'thread_title' => $current_post['post_title'],
4787
            'forum_id' => $current_post['forum_id'],
4788
            'thread_poster_id' => $current_post['poster_id'],
4789
            'thread_poster_name' => $current_post['poster_name'],
4790
            'thread_last_post' => $values['post_id'],
4791
            'thread_date' => $current_post['post_date'],
4792
        ];
4793
4794
        $new_thread_id = Database::insert($table_threads, $params);
4795
4796
        api_item_property_update(
4797
            $_course,
4798
            TOOL_FORUM_THREAD,
4799
            $new_thread_id,
4800
            'visible',
4801
            $current_post['poster_id']
4802
        );
4803
4804
        // Moving the post to the newly created thread.
4805
        $sql = "UPDATE $table_posts SET thread_id='".intval($new_thread_id)."', post_parent_id = NULL
4806
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4807
        Database::query($sql);
4808
4809
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
4810
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4811
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4812
        Database::query($sql);
4813
4814
        // Updating updating the number of threads in the forum.
4815
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
4816
                WHERE c_id = $course_id AND forum_id='".intval($current_post['forum_id'])."'";
4817
        Database::query($sql);
4818
4819
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
4820
        $sql = "SELECT * FROM $table_posts
4821
                WHERE c_id = $course_id AND thread_id='".intval($current_post['thread_id'])."'
4822
                ORDER BY post_id DESC";
4823
        $result = Database::query($sql);
4824
        $row = Database::fetch_array($result);
4825
        $sql = "UPDATE $table_threads SET
4826
                    thread_last_post='".$row['post_id']."',
4827
                    thread_replies=thread_replies-1
4828
                WHERE
4829
                    c_id = $course_id AND
4830
                    thread_id='".intval($current_post['thread_id'])."'";
4831
        Database::query($sql);
4832
    } else {
4833
        // Moving to the chosen thread.
4834
        $sql = "SELECT thread_id FROM ".$table_posts."
4835
                WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
4836
        $result = Database::query($sql);
4837
        $row = Database::fetch_array($result);
4838
4839
        $original_thread_id = $row['thread_id'];
4840
4841
        $sql = "SELECT thread_last_post FROM ".$table_threads."
4842
                WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4843
4844
        $result = Database::query($sql);
4845
        $row = Database::fetch_array($result);
4846
        $thread_is_last_post = $row['thread_last_post'];
4847
        // If is this thread, update the thread_last_post with the last one.
4848
4849
        if ($thread_is_last_post == $values['post_id']) {
4850
            $sql = "SELECT post_id FROM ".$table_posts."
4851
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."'
4852
                    ORDER BY post_date DESC LIMIT 1";
4853
            $result = Database::query($sql);
4854
4855
            $row = Database::fetch_array($result);
4856
            $thread_new_last_post = $row['post_id'];
4857
4858
            $sql = "UPDATE ".$table_threads." SET thread_last_post = '".$thread_new_last_post."'
4859
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4860
            Database::query($sql);
4861
        }
4862
4863
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
4864
                WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
4865
        Database::query($sql);
4866
4867
        // moving to the chosen thread
4868
        $sql = "UPDATE $table_posts SET thread_id='".intval($_POST['thread'])."', post_parent_id = NULL
4869
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4870
        Database::query($sql);
4871
4872
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
4873
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4874
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4875
        Database::query($sql);
4876
4877
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
4878
                WHERE c_id = $course_id AND thread_id='".intval($_POST['thread'])."'";
4879
        Database::query($sql);
4880
    }
4881
4882
    return get_lang('ThreadMoved');
4883
}
4884
4885
/**
4886
 * @param array
4887
 *
4888
 * @return string HTML language variable
4889
 *
4890
 * @author Patrick Cool <[email protected]>, Ghent University
4891
 *
4892
 * @version february 2006, dokeos 1.8
4893
 */
4894
function store_move_thread($values)
4895
{
4896
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4897
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4898
4899
    $courseId = api_get_course_int_id();
4900
    $sessionId = api_get_session_id();
4901
4902
    $forumId = intval($_POST['forum']);
4903
    $threadId = intval($_POST['thread_id']);
4904
    $forumInfo = get_forums($forumId);
4905
4906
    // Change the thread table: Setting the forum_id to the new forum.
4907
    $sql = "UPDATE $table_threads SET forum_id = $forumId
4908
            WHERE c_id = $courseId AND thread_id = $threadId";
4909
    Database::query($sql);
4910
4911
    // Changing all the posts of the thread: setting the forum_id to the new forum.
4912
    $sql = "UPDATE $table_posts SET forum_id = $forumId
4913
            WHERE c_id = $courseId AND thread_id= $threadId";
4914
    Database::query($sql);
4915
    // Fix group id, if forum is moved to a different group
4916
    if (!empty($forumInfo['to_group_id'])) {
4917
        $groupId = $forumInfo['to_group_id'];
4918
        $item = api_get_item_property_info(
4919
            $courseId,
4920
            TABLE_FORUM_THREAD,
4921
            $threadId,
4922
            $sessionId,
4923
            $groupId
4924
        );
4925
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4926
        $sessionCondition = api_get_session_condition($sessionId);
4927
4928
        if (!empty($item)) {
4929
            if ($item['to_group_id'] != $groupId) {
4930
                $sql = "UPDATE $table
4931
                    SET to_group_id = $groupId
4932
                    WHERE
4933
                      tool = '".TABLE_FORUM_THREAD."' AND
4934
                      c_id = $courseId AND
4935
                      ref = ".$item['ref']."
4936
                      $sessionCondition
4937
                ";
4938
                Database::query($sql);
4939
            }
4940
        } else {
4941
            $sql = "UPDATE $table
4942
                    SET to_group_id = $groupId
4943
                    WHERE
4944
                      tool = '".TABLE_FORUM_THREAD."' AND
4945
                      c_id = $courseId AND
4946
                      ref = ".$threadId."
4947
                      $sessionCondition
4948
            ";
4949
            Database::query($sql);
4950
        }
4951
    }
4952
4953
    return get_lang('ThreadMoved');
4954
}
4955
4956
/**
4957
 * Prepares a string for displaying by highlighting the search results inside, if any.
4958
 *
4959
 * @param string $input the input string
4960
 *
4961
 * @return string the same string with highlighted hits inside
4962
 *
4963
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
4964
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
4965
 */
4966
function prepare4display($input)
4967
{
4968
    static $highlightcolors = ['yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33'];
4969
    static $search;
4970
4971
    if (!isset($search)) {
4972
        if (isset($_POST['search_term'])) {
4973
            $search = $_POST['search_term']; // No html at all.
4974
        } elseif (isset($_GET['search'])) {
4975
            $search = $_GET['search'];
4976
        } else {
4977
            $search = '';
4978
        }
4979
    }
4980
4981
    if (!empty($search)) {
4982
        if (strstr($search, '+')) {
4983
            $search_terms = explode('+', $search);
4984
        } else {
4985
            $search_terms[] = trim($search);
4986
        }
4987
        $counter = 0;
4988
        foreach ($search_terms as $key => $search_term) {
4989
            $input = api_preg_replace(
4990
                '/'.preg_quote(trim($search_term), '/').'/i',
4991
                '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
4992
                $input
4993
            );
4994
            $counter++;
4995
        }
4996
    }
4997
4998
    // TODO: Security should be implemented outside this function.
4999
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles
5000
    // (see comments of Security::remove_XSS() method to learn about other levels).
5001
5002
    return Security::remove_XSS($input, STUDENT, true);
5003
}
5004
5005
/**
5006
 * Display the search form for the forum and display the search results.
5007
 *
5008
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5009
 *
5010
 * @version march 2008, dokeos 1.8.5
5011
 */
5012
function forum_search()
5013
{
5014
    $form = new FormValidator(
5015
        'forumsearch',
5016
        'post',
5017
        'forumsearch.php?'.api_get_cidreq()
5018
    );
5019
5020
    // Setting the form elements.
5021
    $form->addElement('header', '', get_lang('ForumSearch'));
5022
    $form->addElement('text', 'search_term', get_lang('SearchTerm'), ['autofocus']);
5023
    $form->applyFilter('search_term', 'html_filter');
5024
    $form->addElement('static', 'search_information', '', get_lang('ForumSearchInformation'));
5025
    $form->addButtonSearch(get_lang('Search'));
5026
5027
    // Setting the rules.
5028
    $form->addRule('search_term', get_lang('ThisFieldIsRequired'), 'required');
5029
    $form->addRule('search_term', get_lang('TooShort'), 'minlength', 3);
5030
5031
    // Validation or display.
5032
    if ($form->validate()) {
5033
        $values = $form->exportValues();
5034
        $form->setDefaults($values);
5035
        $form->display();
5036
        // Display the search results.
5037
        display_forum_search_results(stripslashes($values['search_term']));
5038
    } else {
5039
        $form->display();
5040
    }
5041
}
5042
5043
/**
5044
 * Display the search results.
5045
 *
5046
 * @param string
5047
 * @param string $search_term
5048
 *
5049
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5050
 *
5051
 * @version march 2008, dokeos 1.8.5
5052
 */
5053
function display_forum_search_results($search_term)
5054
{
5055
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5056
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5057
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5058
    $session_id = api_get_session_id();
5059
    $course_id = api_get_course_int_id();
5060
5061
    // Defining the search strings as an array.
5062
    if (strstr($search_term, '+')) {
5063
        $search_terms = explode('+', $search_term);
5064
    } else {
5065
        $search_terms[] = $search_term;
5066
    }
5067
5068
    // Search restriction.
5069
    foreach ($search_terms as $value) {
5070
        $search_restriction[] = "
5071
        (
5072
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR 
5073
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%' 
5074
        )";
5075
    }
5076
5077
    $sessionCondition = api_get_session_condition(
5078
        $session_id,
5079
        true,
5080
        false,
5081
        'item_property.session_id'
5082
    );
5083
5084
    $sql = "SELECT posts.*
5085
            FROM $table_posts posts 
5086
            INNER JOIN $table_threads threads
5087
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5088
            INNER JOIN $table_item_property item_property
5089
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
5090
            WHERE
5091
                posts.c_id = $course_id AND 
5092
                item_property.c_id = $course_id AND 
5093
                item_property.visibility = 1  
5094
                $sessionCondition AND
5095
                posts.visible = 1 AND 
5096
                item_property.tool = '".TOOL_FORUM_THREAD."' AND 
5097
                ".implode(' AND ', $search_restriction)."
5098
            GROUP BY posts.post_id";
5099
5100
    // Getting all the information of the forum categories.
5101
    $forum_categories_list = get_forum_categories();
5102
5103
    // Getting all the information of the forums.
5104
    $forum_list = get_forums();
5105
5106
    $result = Database::query($sql);
5107
    $search_results = [];
5108
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5109
        $forumId = $row['forum_id'];
5110
        $forumData = get_forums($forumId);
5111
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
5112
        $display_result = false;
5113
        /*
5114
          We only show it when
5115
          1. forum category is visible
5116
          2. forum is visible
5117
          3. thread is visible (to do)
5118
          4. post is visible
5119
         */
5120
        if (!api_is_allowed_to_edit(null, true)) {
5121
            if (!empty($category)) {
5122
                if ($category['visibility'] == '1' && $forumData['visibility'] == '1') {
5123
                    $display_result = true;
5124
                }
5125
            } else {
5126
                if ($forumData['visible'] == '1') {
5127
                    $display_result = true;
5128
                }
5129
            }
5130
        } else {
5131
            $display_result = true;
5132
        }
5133
5134
        if ($display_result) {
5135
            $categoryName = !empty($category) ? $category['cat_title'] : '';
5136
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
5137
                prepare4display($categoryName).'</a> &gt; ';
5138
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
5139
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
5140
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
5141
                prepare4display($row['post_title']).'</a>';
5142
            $search_results_item .= '<br />';
5143
            if (api_strlen($row['post_title']) > 200) {
5144
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
5145
            } else {
5146
                $search_results_item .= prepare4display($row['post_title']);
5147
            }
5148
            $search_results_item .= '</li>';
5149
            $search_results[] = $search_results_item;
5150
        }
5151
    }
5152
    echo '<legend>'.count($search_results).' '.get_lang('ForumSearchResults').'</legend>';
5153
    echo '<ol>';
5154
    if ($search_results) {
5155
        echo implode($search_results);
5156
    }
5157
    echo '</ol>';
5158
}
5159
5160
/**
5161
 * Return the link to the forum search page.
5162
 *
5163
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5164
 *
5165
 * @version April 2008, dokeos 1.8.5
5166
 */
5167
function search_link()
5168
{
5169
    $return = '';
5170
    $origin = api_get_origin();
5171
    if ($origin != 'learnpath') {
5172
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
5173
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
5174
5175
        if (!empty($_GET['search'])) {
5176
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
5177
            $url = api_get_self().'?';
5178
            $url_parameter = [];
5179
            foreach ($_GET as $key => $value) {
5180
                if ($key != 'search') {
5181
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
5182
                }
5183
            }
5184
            $url = $url.implode('&', $url_parameter);
5185
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('RemoveSearchResults')).'</a>';
5186
        }
5187
    }
5188
5189
    return $return;
5190
}
5191
5192
/**
5193
 * This function adds an attachment file into a forum.
5194
 *
5195
 * @param string $file_comment a comment about file
5196
 * @param int    $last_id      from forum_post table
5197
 *
5198
 * @return false|null
5199
 */
5200
function add_forum_attachment_file($file_comment, $last_id)
5201
{
5202
    $_course = api_get_course_info();
5203
    $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5204
5205
    if (empty($_FILES['user_upload'])) {
5206
        return false;
5207
    }
5208
5209
    $filesData = [];
5210
5211
    if (!is_array($_FILES['user_upload']['name'])) {
5212
        $filesData[] = $_FILES['user_upload'];
5213
    } else {
5214
        $fileCount = count($_FILES['user_upload']['name']);
5215
        $fileKeys = array_keys($_FILES['user_upload']);
5216
        for ($i = 0; $i < $fileCount; $i++) {
5217
            foreach ($fileKeys as $key) {
5218
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5219
            }
5220
        }
5221
    }
5222
5223
    foreach ($filesData as $attachment) {
5224
        if (empty($attachment['name'])) {
5225
            continue;
5226
        }
5227
5228
        $upload_ok = process_uploaded_file($attachment);
5229
5230
        if (!$upload_ok) {
5231
            continue;
5232
        }
5233
5234
        $course_dir = $_course['path'].'/upload/forum';
5235
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5236
        $updir = $sys_course_path.$course_dir;
5237
5238
        // Try to add an extension to the file if it hasn't one.
5239
        $new_file_name = add_ext_on_mime(
5240
            stripslashes($attachment['name']),
5241
            $attachment['type']
5242
        );
5243
        // User's file name
5244
        $file_name = $attachment['name'];
5245
5246
        if (!filter_extension($new_file_name)) {
5247
            Display::addFlash(
5248
                Display::return_message(
5249
                    get_lang('UplUnableToSaveFileFilteredExtension'),
5250
                    'error'
5251
                )
5252
            );
5253
5254
            return;
5255
        }
5256
5257
        $new_file_name = uniqid('');
5258
        $new_path = $updir.'/'.$new_file_name;
5259
        $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5260
        $safe_file_comment = Database::escape_string($file_comment);
5261
        $safe_file_name = Database::escape_string($file_name);
5262
        $safe_new_file_name = Database::escape_string($new_file_name);
5263
        $last_id = intval($last_id);
5264
        // Storing the attachments if any.
5265
        if (!$result) {
5266
            return;
5267
        }
5268
5269
        $last_id_file = Database::insert(
5270
            $agenda_forum_attachment,
5271
            [
5272
                'c_id' => api_get_course_int_id(),
5273
                'filename' => $safe_file_name,
5274
                'comment' => $safe_file_comment,
5275
                'path' => $safe_new_file_name,
5276
                'post_id' => $last_id,
5277
                'size' => intval($attachment['size']),
5278
            ]
5279
        );
5280
5281
        api_item_property_update(
5282
            $_course,
5283
            TOOL_FORUM_ATTACH,
5284
            $last_id_file,
5285
            'ForumAttachmentAdded',
5286
            api_get_user_id()
5287
        );
5288
    }
5289
}
5290
5291
/**
5292
 * This function edits an attachment file into a forum.
5293
 *
5294
 * @param string $file_comment a comment about file
5295
 * @param int    $post_id
5296
 * @param int    $id_attach    attachment file Id
5297
 */
5298
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
5299
{
5300
    $_course = api_get_course_info();
5301
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5302
    $course_id = api_get_course_int_id();
5303
5304
    $filesData = [];
5305
5306
    if (!is_array($_FILES['user_upload']['name'])) {
5307
        $filesData[] = $_FILES['user_upload'];
5308
    } else {
5309
        $fileCount = count($_FILES['user_upload']['name']);
5310
        $fileKeys = array_keys($_FILES['user_upload']);
5311
5312
        for ($i = 0; $i < $fileCount; $i++) {
5313
            foreach ($fileKeys as $key) {
5314
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5315
            }
5316
        }
5317
    }
5318
5319
    foreach ($filesData as $attachment) {
5320
        if (empty($attachment['name'])) {
5321
            continue;
5322
        }
5323
5324
        $upload_ok = process_uploaded_file($attachment);
5325
5326
        if (!$upload_ok) {
5327
            continue;
5328
        }
5329
5330
        $course_dir = $_course['path'].'/upload/forum';
5331
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5332
        $updir = $sys_course_path.$course_dir;
5333
5334
        // Try to add an extension to the file if it hasn't one.
5335
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
5336
        // User's file name
5337
        $file_name = $attachment['name'];
5338
5339
        if (!filter_extension($new_file_name)) {
5340
            Display::addFlash(
5341
                Display::return_message(
5342
                    get_lang('UplUnableToSaveFileFilteredExtension'),
5343
                    'error'
5344
                )
5345
            );
5346
        } else {
5347
            $new_file_name = uniqid('');
5348
            $new_path = $updir.'/'.$new_file_name;
5349
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5350
            $safe_file_comment = Database::escape_string($file_comment);
5351
            $safe_file_name = Database::escape_string($file_name);
5352
            $safe_new_file_name = Database::escape_string($new_file_name);
5353
            $safe_post_id = (int) $post_id;
5354
            $safe_id_attach = (int) $id_attach;
5355
            // Storing the attachments if any.
5356
            if ($result) {
5357
                $sql = "UPDATE $table_forum_attachment 
5358
                        SET 
5359
                            filename = '$safe_file_name', 
5360
                            comment = '$safe_file_comment', 
5361
                            path = '$safe_new_file_name', 
5362
                            post_id = '$safe_post_id', 
5363
                            size ='".$attachment['size']."'
5364
                        WHERE c_id = $course_id AND id = '$safe_id_attach'";
5365
                Database::query($sql);
5366
                api_item_property_update(
5367
                    $_course,
5368
                    TOOL_FORUM_ATTACH,
5369
                    $safe_id_attach,
5370
                    'ForumAttachmentUpdated',
5371
                    api_get_user_id()
5372
                );
5373
            }
5374
        }
5375
    }
5376
}
5377
5378
/**
5379
 * Show a list with all the attachments according to the post's id.
5380
 *
5381
 * @param int $postId
5382
 *
5383
 * @return array with the post info
5384
 *
5385
 * @author Julio Montoya
5386
 *
5387
 * @version avril 2008, dokeos 1.8.5
5388
 */
5389
function get_attachment($postId)
5390
{
5391
    $table = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5392
    $course_id = api_get_course_int_id();
5393
    $row = [];
5394
    $postId = (int) $postId;
5395
5396
    if (empty($postId)) {
5397
        return [];
5398
    }
5399
5400
    $sql = "SELECT iid, path, filename, comment 
5401
            FROM $table
5402
            WHERE c_id = $course_id AND post_id = $postId";
5403
    $result = Database::query($sql);
5404
    if (Database::num_rows($result) != 0) {
5405
        $row = Database::fetch_array($result);
5406
    }
5407
5408
    return $row;
5409
}
5410
5411
/**
5412
 * @param int $postId
5413
 *
5414
 * @return array
5415
 */
5416
function getAllAttachment($postId)
5417
{
5418
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5419
    $courseId = api_get_course_int_id();
5420
    $postId = (int) $postId;
5421
5422
    if (empty($postId)) {
5423
        return [];
5424
    }
5425
5426
    $columns = ['iid', 'path', 'filename', 'comment'];
5427
    $conditions = [
5428
        'where' => [
5429
            'c_id = ? AND post_id = ?' => [$courseId, $postId],
5430
        ],
5431
    ];
5432
    $array = Database::select(
5433
        $columns,
5434
        $forumAttachmentTable,
5435
        $conditions,
5436
        'all',
5437
        'ASSOC'
5438
    );
5439
5440
    return $array;
5441
}
5442
5443
/**
5444
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional).
5445
 *
5446
 * @param int $post_id
5447
 * @param int $id_attach
5448
 *
5449
 * @return int
5450
 *
5451
 * @author Julio Montoya
5452
 *
5453
 * @version october 2014, chamilo 1.9.8
5454
 */
5455
function delete_attachment($post_id, $id_attach = 0)
5456
{
5457
    $_course = api_get_course_info();
5458
5459
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5460
    $course_id = api_get_course_int_id();
5461
5462
    $cond = (!empty($id_attach)) ? " iid = ".(int) $id_attach."" : " post_id = ".(int) $post_id."";
5463
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
5464
    $res = Database::query($sql);
5465
    $row = Database::fetch_array($res);
5466
5467
    $course_dir = $_course['path'].'/upload/forum';
5468
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
5469
    $updir = $sys_course_path.$course_dir;
5470
    $my_path = isset($row['path']) ? $row['path'] : null;
5471
    $file = $updir.'/'.$my_path;
5472
    if (Security::check_abs_path($file, $updir)) {
5473
        @unlink($file);
5474
    }
5475
5476
    // Delete from forum_attachment table.
5477
    $sql = "DELETE FROM $forum_table_attachment 
5478
            WHERE c_id = $course_id AND $cond ";
5479
    $result = Database::query($sql);
5480
    if ($result !== false) {
5481
        $affectedRows = Database::affected_rows($result);
5482
    } else {
5483
        $affectedRows = 0;
5484
    }
5485
5486
    // Update item_property.
5487
    api_item_property_update(
5488
        $_course,
5489
        TOOL_FORUM_ATTACH,
5490
        $id_attach,
5491
        'ForumAttachmentDelete',
5492
        api_get_user_id()
5493
    );
5494
5495
    if (!empty($result) && !empty($id_attach)) {
5496
        Display::addFlash(Display::return_message(get_lang('AttachmentFileDeleteSuccess'), 'confirmation'));
5497
    }
5498
5499
    return $affectedRows;
5500
}
5501
5502
/**
5503
 * This function gets all the forum information of the all the forum of the group.
5504
 *
5505
 * @param array $groupInfo the id of the group we need the fora of (see forum.forum_of_group)
5506
 *
5507
 * @return array
5508
 *
5509
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
5510
 */
5511
function get_forums_of_group($groupInfo)
5512
{
5513
    $table_forums = Database::get_course_table(TABLE_FORUM);
5514
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5515
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5516
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5517
    $course_id = api_get_course_int_id();
5518
    $groupId = (int) $groupInfo['id'];
5519
5520
    // Student
5521
    // Select all the forum information of all forums (that are visible to students).
5522
    $sql = "SELECT * FROM $table_forums forum 
5523
            INNER JOIN $table_item_property item_properties
5524
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5525
            WHERE
5526
                forum.forum_of_group = $groupId AND
5527
                forum.c_id = $course_id AND
5528
                item_properties.c_id = $course_id AND                
5529
                item_properties.visibility = 1 AND
5530
                item_properties.tool = '".TOOL_FORUM."'
5531
            ORDER BY forum.forum_order ASC";
5532
5533
    // Select the number of threads of the forums (only the threads that are visible).
5534
    $sql2 = "SELECT 
5535
                count(thread_id) AS number_of_threads, 
5536
                threads.forum_id
5537
            FROM $table_threads threads 
5538
            INNER JOIN $table_item_property item_properties
5539
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5540
            WHERE                
5541
                threads.c_id = $course_id AND
5542
                item_properties.c_id = $course_id AND
5543
                item_properties.visibility = 1 AND
5544
                item_properties.tool='".TOOL_FORUM_THREAD."'
5545
            GROUP BY threads.forum_id";
5546
5547
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
5548
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
5549
            FROM $table_posts posts 
5550
            INNER JOIN $table_threads threads 
5551
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5552
            INNER JOIN $table_item_property item_properties
5553
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5554
            WHERE 
5555
                posts.visible=1 AND
5556
                posts.c_id = $course_id AND
5557
                item_properties.c_id = $course_id AND
5558
                threads.c_id = $course_id AND 
5559
                item_properties.visibility = 1 AND 
5560
                item_properties.tool='".TOOL_FORUM_THREAD."'
5561
            GROUP BY threads.forum_id";
5562
5563
    // Course Admin
5564
    if (api_is_allowed_to_edit()) {
5565
        // Select all the forum information of all forums (that are not deleted).
5566
        $sql = "SELECT *
5567
                FROM $table_forums forum 
5568
                INNER JOIN $table_item_property item_properties
5569
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5570
                WHERE
5571
                    forum.forum_of_group = $groupId AND
5572
                    forum.c_id = $course_id AND
5573
                    item_properties.c_id = $course_id AND                    
5574
                    item_properties.visibility <> 2 AND
5575
                    item_properties.tool = '".TOOL_FORUM."'
5576
                ORDER BY forum_order ASC";
5577
5578
        // Select the number of threads of the forums (only the threads that are not deleted).
5579
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
5580
                 FROM $table_threads threads 
5581
                 INNER JOIN $table_item_property item_properties
5582
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
5583
                 WHERE
5584
                    threads.c_id = $course_id AND
5585
                    item_properties.c_id = $course_id AND
5586
                    item_properties.visibility <> 2 AND
5587
                    item_properties.tool='".TOOL_FORUM_THREAD."'
5588
                GROUP BY threads.forum_id";
5589
        // Select the number of posts of the forum.
5590
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
5591
                FROM $table_posts
5592
                WHERE c_id = $course_id 
5593
                GROUP BY forum_id";
5594
    }
5595
5596
    // Handling all the forum information.
5597
    $result = Database::query($sql);
5598
    $forum_list = [];
5599
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5600
        $forum_list[$row['forum_id']] = $row;
5601
    }
5602
5603
    // Handling the thread count information.
5604
    $result2 = Database::query($sql2);
5605
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5606
        if (is_array($forum_list)) {
5607
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5608
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5609
            }
5610
        }
5611
    }
5612
5613
    // Handling the post count information.
5614
    $result3 = Database::query($sql3);
5615
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5616
        if (is_array($forum_list)) {
5617
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5618
                // This is needed because sql3 takes also the deleted forums into account.
5619
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5620
            }
5621
        }
5622
    }
5623
5624
    // Finding the last post information
5625
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5626
    if (!empty($forum_list)) {
5627
        foreach ($forum_list as $key => $value) {
5628
            $lastPost = get_last_post_information($key, api_is_allowed_to_edit());
5629
            if ($lastPost) {
5630
                $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
5631
                $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
5632
                $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
5633
                $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
5634
                $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
5635
                $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
5636
            }
5637
        }
5638
    }
5639
5640
    return $forum_list;
5641
}
5642
5643
/**
5644
 * This function stores which users have to be notified of which forums or threads.
5645
 *
5646
 * @param string $content    does the user want to be notified about a forum or about a thread
5647
 * @param int    $id         the id of the forum or thread
5648
 * @param bool   $addOnly
5649
 * @param array  $userInfo
5650
 * @param array  $courseInfo
5651
 *
5652
 * @return string language variable
5653
 *
5654
 * @author  Patrick Cool <[email protected]>, Ghent University, Belgium
5655
 * @author  Julio Montoya
5656
 *
5657
 * @since   May 2008 v1.8.5
5658
 */
5659
function set_notification($content, $id, $addOnly = false, $userInfo = [], $courseInfo = [])
5660
{
5661
    $userInfo = empty($userInfo) ? api_get_user_info() : $userInfo;
5662
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
5663
    $id = (int) $id;
5664
5665
    if (empty($userInfo) || empty($courseInfo) || empty($id) || empty($content)) {
5666
        return false;
5667
    }
5668
5669
    // Database table definition
5670
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5671
5672
    $course_id = $courseInfo['real_id'];
5673
5674
    // Which database field do we have to store the id in?
5675
    $field = 'thread_id';
5676
    if ($content === 'forum') {
5677
        $field = 'forum_id';
5678
    }
5679
5680
    $userId = $userInfo['user_id'];
5681
5682
    // First we check if the notification is already set for this.
5683
    $sql = "SELECT * FROM $table_notification
5684
            WHERE
5685
                c_id = $course_id AND
5686
                $field = $id AND
5687
                user_id = $userId ";
5688
    $result = Database::query($sql);
5689
    $total = Database::num_rows($result);
5690
5691
    // If the user did not indicate that (s)he wanted to be notified already
5692
    // then we store the notification request (to prevent double notification requests).
5693
    if ($total <= 0) {
5694
        $sql = "INSERT INTO $table_notification (c_id, $field, user_id)
5695
                VALUES ($course_id, '$id','$userId')";
5696
        Database::query($sql);
5697
        Session::erase('forum_notification');
5698
        getNotificationsPerUser(0, true);
5699
5700
        return get_lang('YouWillBeNotifiedOfNewPosts');
5701
    } else {
5702
        if (!$addOnly) {
5703
            $sql = "DELETE FROM $table_notification
5704
                    WHERE
5705
                        c_id = $course_id AND
5706
                        $field = $id AND
5707
                        user_id = $userId ";
5708
            Database::query($sql);
5709
            Session::erase('forum_notification');
5710
            getNotificationsPerUser(0, true);
5711
5712
            return get_lang('YouWillNoLongerBeNotifiedOfNewPosts');
5713
        }
5714
    }
5715
}
5716
5717
/**
5718
 * This function retrieves all the email adresses of the users who wanted to be notified
5719
 * about a new post in a certain forum or thread.
5720
 *
5721
 * @param string $content does the user want to be notified about a forum or about a thread
5722
 * @param int    $id      the id of the forum or thread
5723
 *
5724
 * @return array returns
5725
 *
5726
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5727
 * @author Julio Montoya
5728
 *
5729
 * @version May 2008, dokeos 1.8.5
5730
 *
5731
 * @since May 2008, dokeos 1.8.5
5732
 */
5733
function get_notifications($content, $id)
5734
{
5735
    // Database table definition
5736
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5737
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5738
    $course_id = api_get_course_int_id();
5739
5740
    // Which database field contains the notification?
5741
    $field = 'thread_id';
5742
    if ($content === 'forum') {
5743
        $field = 'forum_id';
5744
    }
5745
5746
    $id = (int) $id;
5747
5748
    $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
5749
            FROM $table_users user, $table_notification notification
5750
            WHERE 
5751
                notification.c_id = $course_id AND user.active = 1 AND
5752
                user.user_id = notification.user_id AND
5753
                notification.$field = $id ";
5754
5755
    $result = Database::query($sql);
5756
    $return = [];
5757
5758
    while ($row = Database::fetch_array($result)) {
5759
        $return['user'.$row['user_id']] = ['email' => $row['email'], 'user_id' => $row['user_id']];
5760
    }
5761
5762
    return $return;
5763
}
5764
5765
/**
5766
 * Get all the users who need to receive a notification of a new post (those subscribed to
5767
 * the forum or the thread).
5768
 *
5769
 * @param int $forum_id  the id of the forum
5770
 * @param int $thread_id the id of the thread
5771
 * @param int $post_id   the id of the post
5772
 *
5773
 * @return false|null
5774
 *
5775
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5776
 *
5777
 * @version May 2008, dokeos 1.8.5
5778
 *
5779
 * @since May 2008, dokeos 1.8.5
5780
 */
5781
function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
5782
{
5783
    $forum_id = (int) $forum_id;
5784
    // Users who subscribed to the forum
5785
    if ($forum_id != 0) {
5786
        $users_to_be_notified_by_forum = get_notifications('forum', $forum_id);
5787
    } else {
5788
        return false;
5789
    }
5790
5791
    $current_thread = get_thread_information($forum_id, $thread_id);
5792
    $courseInfo = api_get_course_info_by_id($current_thread['c_id']);
5793
    $courseCode = $courseInfo['code'];
5794
5795
    // User who subscribed to the thread
5796
    if ($thread_id != 0) {
5797
        $users_to_be_notified_by_thread = get_notifications('thread', $thread_id);
5798
    }
5799
5800
    $postInfo = [];
5801
    if (!empty($post_id)) {
5802
        $postInfo = get_post_information($post_id);
5803
    }
5804
5805
    // Merging the two
5806
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
5807
    $forumInfo = get_forum_information($forum_id);
5808
5809
    if (is_array($users_to_be_notified)) {
5810
        foreach ($users_to_be_notified as $value) {
5811
            $notifyUser = true;
5812
            if ((api_get_course_setting('share_forums_in_sessions',$courseCode) === -1 || !api_get_course_setting('share_forums_in_sessions',$courseCode)) && $current_thread['session_id'] != 0) {
5813
                $notifyUser = false;
5814
                $userSessions = SessionManager::get_sessions_by_user($value['user_id']);
5815
                foreach ($userSessions as $userSession) {
5816
                    if ($userSession['session_id'] == $current_thread['session_id']) {
5817
                        $notifyUser = true;
5818
                    }
5819
                }
5820
            }
5821
            if ($notifyUser === true) {
5822
                $userInfo = api_get_user_info($value['user_id']);
5823
                send_mail($userInfo, $forumInfo, $current_thread, $postInfo);
5824
            }
5825
        }
5826
    }
5827
}
5828
5829
/**
5830
 * Get all the notification subscriptions of the user
5831
 * = which forums and which threads does the user wants to be informed of when a new
5832
 * post is added to this thread.
5833
 *
5834
 * @param int  $user_id the user_id of a user (default = 0 => the current user)
5835
 * @param bool $force   force get the notification subscriptions (even if the information is already in the session
5836
 *
5837
 * @return array
5838
 *
5839
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5840
 *
5841
 * @version May 2008, dokeos 1.8.5
5842
 *
5843
 * @since May 2008, dokeos 1.8.5
5844
 */
5845
function getNotificationsPerUser($user_id = 0, $force = false, $course_id = 0)
5846
{
5847
    // Database table definition
5848
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5849
    $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
5850
    if (empty($course_id) || $course_id == -1) {
5851
        return null;
5852
    }
5853
5854
    $user_id = empty($user_id) ? api_get_user_id() : (int) $user_id;
5855
5856
    if (!isset($_SESSION['forum_notification']) ||
5857
        $_SESSION['forum_notification']['course'] != $course_id ||
5858
        $force == true
5859
    ) {
5860
        $_SESSION['forum_notification']['course'] = $course_id;
5861
        $sql = "SELECT * FROM $table_notification
5862
                WHERE c_id = $course_id AND user_id='".$user_id."'";
5863
5864
        $result = Database::query($sql);
5865
        while ($row = Database::fetch_array($result)) {
5866
            if (!is_null($row['forum_id'])) {
5867
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
5868
            }
5869
            if (!is_null($row['thread_id'])) {
5870
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
5871
            }
5872
        }
5873
    }
5874
}
5875
5876
/**
5877
 * This function counts the number of post inside a thread.
5878
 *
5879
 * @param int $thread_id
5880
 *
5881
 * @return int the number of post inside a thread
5882
 *
5883
 * @author Jhon Hinojosa <[email protected]>,
5884
 *
5885
 * @version octubre 2008, dokeos 1.8
5886
 */
5887
function count_number_of_post_in_thread($thread_id)
5888
{
5889
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5890
    $course_id = api_get_course_int_id();
5891
    if (empty($course_id)) {
5892
        return 0;
5893
    }
5894
    $sql = "SELECT count(*) count FROM $table_posts
5895
            WHERE 
5896
                c_id = $course_id AND 
5897
                thread_id='".intval($thread_id)."' ";
5898
    $result = Database::query($sql);
5899
5900
    $count = 0;
5901
    if (Database::num_rows($result) > 0) {
5902
        $row = Database::fetch_array($result);
5903
        $count = $row['count'];
5904
    }
5905
5906
    return $count;
5907
}
5908
5909
/**
5910
 * This function counts the number of post inside a thread user.
5911
 *
5912
 * @param int $thread_id
5913
 * @param int $user_id
5914
 *
5915
 * @return int the number of post inside a thread user
5916
 */
5917
function count_number_of_post_for_user_thread($thread_id, $user_id)
5918
{
5919
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5920
    $course_id = api_get_course_int_id();
5921
    $sql = "SELECT count(iid) as count 
5922
            FROM $table_posts
5923
            WHERE c_id = $course_id AND
5924
                  thread_id=".intval($thread_id)." AND
5925
                  poster_id = ".intval($user_id)." AND visible = 1 ";
5926
    $result = Database::query($sql);
5927
    $count = 0;
5928
    if (Database::num_rows($result) > 0) {
5929
        $count = Database::fetch_array($result);
5930
        $count = $count['count'];
5931
    }
5932
5933
    return $count;
5934
}
5935
5936
/**
5937
 * This function retrieves information of statistical.
5938
 *
5939
 * @param int $thread_id
5940
 * @param int $user_id
5941
 * @param int $course_id
5942
 *
5943
 * @return array the information of statistical
5944
 *
5945
 * @author Jhon Hinojosa <[email protected]>,
5946
 *
5947
 * @version oct 2008, dokeos 1.8
5948
 */
5949
function get_statistical_information($thread_id, $user_id, $course_id)
5950
{
5951
    $result = [];
5952
    $courseInfo = api_get_course_info_by_id($course_id);
5953
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
5954
    $result['post'] = count_number_of_post_in_thread($thread_id);
5955
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
5956
5957
    return $result;
5958
}
5959
5960
/**
5961
 * This function return the posts inside a thread from a given user.
5962
 *
5963
 * @param string $course_code
5964
 * @param int    $thread_id
5965
 * @param int    $user_id
5966
 *
5967
 * @return array posts inside a thread
5968
 *
5969
 * @author Jhon Hinojosa <[email protected]>,
5970
 *
5971
 * @version oct 2008, dokeos 1.8
5972
 */
5973
function get_thread_user_post($course_code, $thread_id, $user_id)
5974
{
5975
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5976
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5977
    $thread_id = intval($thread_id);
5978
    $user_id = intval($user_id);
5979
    $course_info = api_get_user_info($course_code);
5980
    $course_id = $course_info['real_id'];
5981
5982
    if (empty($course_id)) {
5983
        $course_id = api_get_course_int_id();
5984
    }
5985
    $sql = "SELECT * FROM $table_posts posts
5986
            LEFT JOIN  $table_users users
5987
                ON posts.poster_id=users.user_id
5988
            WHERE
5989
                posts.c_id = $course_id AND
5990
                posts.thread_id='$thread_id'
5991
                AND posts.poster_id='$user_id'
5992
            ORDER BY posts.post_id ASC";
5993
5994
    $result = Database::query($sql);
5995
    $post_list = [];
5996
    while ($row = Database::fetch_array($result)) {
5997
        $row['status'] = '1';
5998
        $post_list[] = $row;
5999
        $sql = "SELECT * FROM $table_posts posts
6000
                LEFT JOIN $table_users users
6001
                ON (posts.poster_id=users.user_id)
6002
                WHERE
6003
                    posts.c_id = $course_id AND
6004
                    posts.thread_id='$thread_id'
6005
                    AND posts.post_parent_id='".$row['post_id']."'
6006
                ORDER BY posts.post_id ASC";
6007
        $result2 = Database::query($sql);
6008
        while ($row2 = Database::fetch_array($result2)) {
6009
            $row2['status'] = '0';
6010
            $post_list[] = $row2;
6011
        }
6012
    }
6013
6014
    return $post_list;
6015
}
6016
6017
/**
6018
 * This function get the name of an thread by id.
6019
 *
6020
 * @param int thread_id
6021
 *
6022
 * @return string
6023
 *
6024
 * @author Christian Fasanando
6025
 * @author Julio Montoya <[email protected]> Adding security
6026
 */
6027
function get_name_thread_by_id($thread_id)
6028
{
6029
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
6030
    $course_id = api_get_course_int_id();
6031
    $sql = "SELECT thread_title 
6032
            FROM $t_forum_thread
6033
            WHERE c_id = $course_id AND thread_id = '".intval($thread_id)."' ";
6034
    $result = Database::query($sql);
6035
    $row = Database::fetch_array($result);
6036
6037
    return $row[0];
6038
}
6039
6040
/**
6041
 * This function gets all the post written by an user.
6042
 *
6043
 * @param int    $user_id
6044
 * @param string $course_code
6045
 *
6046
 * @return string
6047
 */
6048
function get_all_post_from_user($user_id, $course_code)
6049
{
6050
    $j = 0;
6051
    $forums = get_forums('', $course_code);
6052
    krsort($forums);
6053
    $forum_results = '';
6054
6055
    foreach ($forums as $forum) {
6056
        if ($forum['visibility'] == 0) {
6057
            continue;
6058
        }
6059
        if ($j <= 4) {
6060
            $threads = get_threads($forum['forum_id']);
6061
6062
            if (is_array($threads)) {
6063
                $i = 0;
6064
                $hand_forums = '';
6065
                $post_counter = 0;
6066
                foreach ($threads as $thread) {
6067
                    if ($thread['visibility'] == 0) {
6068
                        continue;
6069
                    }
6070
                    if ($i <= 4) {
6071
                        $post_list = get_thread_user_post_limit(
6072
                            $course_code,
6073
                            $thread['thread_id'],
6074
                            $user_id,
6075
                            1
6076
                        );
6077
                        $post_counter = count($post_list);
6078
                        if (is_array($post_list) && count($post_list) > 0) {
6079
                            $hand_forums .= '<div id="social-thread">';
6080
                            $hand_forums .= Display::return_icon(
6081
                                'thread.png',
6082
                                get_lang('Thread'),
6083
                                '',
6084
                                ICON_SIZE_MEDIUM
6085
                            );
6086
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
6087
                            $hand_forums .= '</div>';
6088
6089
                            foreach ($post_list as $posts) {
6090
                                $hand_forums .= '<div id="social-post">';
6091
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
6092
                                $hand_forums .= '<br / >';
6093
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
6094
                                $hand_forums .= '</div>';
6095
                                $hand_forums .= '<br / >';
6096
                            }
6097
                        }
6098
                    }
6099
                    $i++;
6100
                }
6101
                $forum_results .= '<div id="social-forum">';
6102
                $forum_results .= '<div class="clear"></div><br />';
6103
                $forum_results .= '<div id="social-forum-title">'.
6104
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum['forum_title'], STUDENT).
6105
                    '<div style="float:right;margin-top:-35px">
6106
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($course_code).'&forum='.$forum['forum_id'].' " >'.
6107
                    get_lang('SeeForum').'    
6108
                        </a>
6109
                     </div></div>';
6110
                $forum_results .= '<br / >';
6111
                if ($post_counter > 0) {
6112
                    $forum_results .= $hand_forums;
6113
                }
6114
                $forum_results .= '</div>';
6115
            }
6116
            $j++;
6117
        }
6118
    }
6119
6120
    return $forum_results;
6121
}
6122
6123
/**
6124
 * @param string $course_code
6125
 * @param int    $thread_id
6126
 * @param int    $user_id
6127
 * @param int    $limit
6128
 *
6129
 * @return array
6130
 */
6131
function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
6132
{
6133
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6134
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
6135
6136
    $course_info = api_get_course_info($course_code);
6137
    $course_id = $course_info['real_id'];
6138
    $limit = (int) $limit;
6139
6140
    $sql = "SELECT * FROM $table_posts posts
6141
            LEFT JOIN  $table_users users
6142
                ON posts.poster_id=users.user_id
6143
            WHERE
6144
                posts.c_id = $course_id AND
6145
                posts.thread_id='".Database::escape_string($thread_id)."' AND 
6146
                posts.poster_id='".Database::escape_string($user_id)."'
6147
            ORDER BY posts.post_id DESC
6148
            LIMIT $limit ";
6149
    $result = Database::query($sql);
6150
    $post_list = [];
6151
    while ($row = Database::fetch_array($result)) {
6152
        $row['status'] = '1';
6153
        $post_list[] = $row;
6154
    }
6155
6156
    return $post_list;
6157
}
6158
6159
/**
6160
 * @param string $userId
6161
 * @param array  $courseInfo
6162
 * @param int    $sessionId
6163
 *
6164
 * @return array
6165
 */
6166
function getForumCreatedByUser($userId, $courseInfo, $sessionId)
6167
{
6168
    if (empty($userId) || empty($courseInfo)) {
6169
        return [];
6170
    }
6171
6172
    $courseId = $courseInfo['real_id'];
6173
    $items = api_get_item_property_list_by_tool_by_user(
6174
        $userId,
6175
        'forum',
6176
        $courseId,
6177
        $sessionId
6178
    );
6179
6180
    $forumList = [];
6181
    if (!empty($items)) {
6182
        foreach ($items as $forum) {
6183
            $forumInfo = get_forums(
6184
                $forum['ref'],
6185
                $courseInfo['code'],
6186
                true,
6187
                $sessionId
6188
            );
6189
            if (!empty($forumInfo) && isset($forumInfo['forum_title'])) {
6190
                $forumList[] = [
6191
                    $forumInfo['forum_title'],
6192
                    api_get_local_time($forum['insert_date']),
6193
                    api_get_local_time($forum['lastedit_date']),
6194
                ];
6195
            }
6196
        }
6197
    }
6198
6199
    return $forumList;
6200
}
6201
6202
/**
6203
 * This function builds an array of all the posts in a given thread
6204
 * where the key of the array is the post_id
6205
 * It also adds an element children to the array which itself is an array
6206
 * that contains all the id's of the first-level children.
6207
 *
6208
 * @return array $rows containing all the information on the posts of a thread
6209
 *
6210
 * @author Patrick Cool <[email protected]>, Ghent University
6211
 */
6212
function calculate_children($rows)
6213
{
6214
    $sorted_rows = [0 => []];
6215
    if (!empty($rows)) {
6216
        foreach ($rows as $row) {
6217
            $rows_with_children[$row['post_id']] = $row;
6218
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
6219
        }
6220
6221
        $rows = $rows_with_children;
6222
        forumRecursiveSort($rows, $sorted_rows);
6223
        unset($sorted_rows[0]);
6224
    }
6225
6226
    return $sorted_rows;
6227
}
6228
6229
/**
6230
 * @param $rows
6231
 * @param $threads
6232
 * @param int $seed
6233
 * @param int $indent
6234
 */
6235
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
6236
{
6237
    if ($seed > 0) {
6238
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
6239
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
6240
        $indent++;
6241
    }
6242
6243
    if (isset($rows[$seed]['children'])) {
6244
        foreach ($rows[$seed]['children'] as $child) {
6245
            forumRecursiveSort($rows, $threads, $child, $indent);
6246
        }
6247
    }
6248
}
6249
6250
/**
6251
 * Update forum attachment data, used to update comment and post ID.
6252
 *
6253
 * @param $array array (field => value) to update forum attachment row
6254
 * @param $id attach ID to find row to update
6255
 * @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...
6256
 *
6257
 * @return int number of affected rows
6258
 */
6259
function editAttachedFile($array, $id, $courseId = null)
6260
{
6261
    // Init variables
6262
    $setString = '';
6263
    $id = (int) $id;
6264
    $courseId = (int) $courseId;
6265
    if (empty($courseId)) {
6266
        // $courseId can be null, use api method
6267
        $courseId = api_get_course_int_id();
6268
    }
6269
    /*
6270
     * Check if Attachment ID and Course ID are greater than zero
6271
     * and array of field values is not empty
6272
     */
6273
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
6274
        foreach ($array as $key => &$item) {
6275
            $item = Database::escape_string($item);
6276
            $setString .= $key.' = "'.$item.'", ';
6277
        }
6278
        // Delete last comma
6279
        $setString = substr($setString, 0, strlen($setString) - 2);
6280
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6281
        $sql = "UPDATE $forumAttachmentTable 
6282
                SET $setString WHERE c_id = $courseId AND id = $id";
6283
        $result = Database::query($sql);
6284
        if ($result !== false) {
6285
            $affectedRows = Database::affected_rows($result);
6286
            if ($affectedRows > 0) {
6287
                /*
6288
                 * If exist in $_SESSION variable, then delete them from it
6289
                 * because they would be deprecated
6290
                 */
6291
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
6292
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
6293
                }
6294
            }
6295
6296
            return $affectedRows;
6297
        }
6298
    }
6299
6300
    return 0;
6301
}
6302
6303
/**
6304
 * Return a table where the attachments will be set.
6305
 *
6306
 * @param int $postId Forum Post ID
6307
 *
6308
 * @return string The Forum Attachments Ajax Table
6309
 */
6310
function getAttachmentsAjaxTable($postId = 0)
6311
{
6312
    $postId = (int) $postId;
6313
    $courseId = api_get_course_int_id();
6314
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6315
    $fileDataContent = '';
6316
    // Update comment to show if form did not pass validation
6317
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
6318
        // 'file_ids is the name from forum attachment ajax form
6319
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
6320
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
6321
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
6322
            ) {
6323
                // If exist forum attachment then update into $_SESSION data
6324
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
6325
            }
6326
        }
6327
    }
6328
6329
    // Get data to fill into attachment files table
6330
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6331
        is_array($_SESSION['forum']['upload_file'][$courseId])
6332
    ) {
6333
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
6334
        foreach ($uploadedFiles as $k => $uploadedFile) {
6335
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
6336
                // Buil html table including an input with attachmentID
6337
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
6338
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
6339
                    $uploadedFile['delete'].'</td>'.
6340
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
6341
            } else {
6342
                /*
6343
                 * If attachment data is empty, then delete it from $_SESSION
6344
                 * because could generate and empty row into html table
6345
                 */
6346
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
6347
            }
6348
        }
6349
    }
6350
    $style = empty($fileDataContent) ? 'display: none;' : '';
6351
    // Forum attachment Ajax table
6352
    $fileData = '
6353
    <div class="control-group " style="'.$style.'">
6354
        <label class="control-label">'.get_lang('AttachmentList').'</label>
6355
        <div class="controls">
6356
            <table id="attachmentFileList" class="files data_table span10">
6357
                <tr>
6358
                    <th>'.get_lang('FileName').'</th>
6359
                    <th>'.get_lang('Size').'</th>
6360
                    <th>'.get_lang('Status').'</th>
6361
                    <th>'.get_lang('Comment').'</th>
6362
                    <th>'.get_lang('Delete').'</th>
6363
                </tr>
6364
                '.$fileDataContent.'
6365
            </table>
6366
        </div>
6367
    </div>';
6368
6369
    return $fileData;
6370
}
6371
6372
/**
6373
 * Return an array of prepared attachment data to build forum attachment table
6374
 * Also, save this array into $_SESSION to do available the attachment data.
6375
 *
6376
 * @param int $forumId
6377
 * @param int $threadId
6378
 * @param int $postId
6379
 * @param int $attachId
6380
 * @param int $courseId
6381
 *
6382
 * @return array
6383
 */
6384
function getAttachedFiles(
6385
    $forumId,
6386
    $threadId,
6387
    $postId = 0,
6388
    $attachId = 0,
6389
    $courseId = 0
6390
) {
6391
    $forumId = (int) $forumId;
6392
    $courseId = (int) $courseId;
6393
    $attachId = (int) $attachId;
6394
    $postId = (int) $postId;
6395
    $threadId = (int) $threadId;
6396
6397
    if (empty($courseId)) {
6398
        // $courseId can be null, use api method
6399
        $courseId = api_get_course_int_id();
6400
    }
6401
    if (empty($forumId)) {
6402
        if (!empty($_REQUEST['forum'])) {
6403
            $forumId = (int) $_REQUEST['forum'];
6404
        } else {
6405
            // if forum ID is empty, cannot generate delete url
6406
6407
            return [];
6408
        }
6409
    }
6410
    // Check if exist at least one of them to filter forum attachment select query
6411
    if (empty($postId) && empty($attachId)) {
6412
        return [];
6413
    } elseif (empty($postId)) {
6414
        $filter = "AND iid = $attachId";
6415
    } elseif (empty($attachId)) {
6416
        $filter = "AND post_id = $postId";
6417
    } else {
6418
        $filter = "AND post_id = $postId AND iid = $attachId";
6419
    }
6420
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6421
    $sql = "SELECT iid, comment, filename, path, size
6422
            FROM $forumAttachmentTable
6423
            WHERE c_id = $courseId $filter";
6424
    $result = Database::query($sql);
6425
    $json = [];
6426
    if ($result !== false && Database::num_rows($result) > 0) {
6427
        while ($row = Database::fetch_array($result, 'ASSOC')) {
6428
            // name contains an URL to download attachment file and its filename
6429
            $json['name'] = Display::url(
6430
                api_htmlentities($row['filename']),
6431
                api_get_path(WEB_CODE_PATH).'forum/download.php?file='.$row['path'].'&'.api_get_cidreq(),
6432
                ['target' => '_blank', 'class' => 'attachFilename']
6433
            );
6434
            $json['id'] = $row['iid'];
6435
            $json['comment'] = $row['comment'];
6436
            // Format file size
6437
            $json['size'] = format_file_size($row['size']);
6438
            // Check if $row is consistent
6439
            if (!empty($row) && is_array($row)) {
6440
                // Set result as success and bring delete URL
6441
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded'));
6442
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
6443
                $json['delete'] = Display::url(
6444
                    Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL),
6445
                    $url,
6446
                    ['class' => 'deleteLink']
6447
                );
6448
            } else {
6449
                // If not, set an exclamation result
6450
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
6451
            }
6452
            // Store array data into $_SESSION
6453
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
6454
        }
6455
    }
6456
6457
    return $json;
6458
}
6459
6460
/**
6461
 * Clear forum attachment data stored in $_SESSION,
6462
 * If is not defined post, it will clear all forum attachment data from course.
6463
 *
6464
 * @param int $postId   -1 : Clear all attachments from course stored in $_SESSION
6465
 *                      0 : Clear attachments from course, except from temporal post "0"
6466
 *                      but without delete them from file system and database
6467
 *                      Other values : Clear attachments from course except specified post
6468
 *                      and delete them from file system and database
6469
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
6470
 *
6471
 * @return array
6472
 */
6473
function clearAttachedFiles($postId = 0, $courseId = 0)
6474
{
6475
    // Init variables
6476
    $courseId = (int) $courseId;
6477
    $postId = (int) $postId;
6478
    $array = [];
6479
    if (empty($courseId)) {
6480
        // $courseId can be null, use api method
6481
        $courseId = api_get_course_int_id();
6482
    }
6483
    if ($postId === -1) {
6484
        // If post ID is -1 then delete course's attachment data from $_SESSION
6485
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
6486
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
6487
            unset($_SESSION['forum']['upload_file'][$courseId]);
6488
        }
6489
    } else {
6490
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6491
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6492
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
6493
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
6494
                if (!in_array($attachId, $attachIds)) {
6495
                    // If attach ID is not into specified post, delete attachment
6496
                    // Save deleted attachment ID
6497
                    $array[] = $attachId;
6498
                    if ($postId !== 0) {
6499
                        // Post 0 is temporal, delete them from file system and DB
6500
                        delete_attachment(0, $attachId);
6501
                    }
6502
                    // Delete attachment data from $_SESSION
6503
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
6504
                }
6505
            }
6506
        }
6507
    }
6508
6509
    return $array;
6510
}
6511
6512
/**
6513
 * Returns an array of forum attachment ids into a course and forum post.
6514
 *
6515
 * @param int $postId
6516
 * @param int $courseId
6517
 *
6518
 * @return array
6519
 */
6520
function getAttachmentIdsByPostId($postId, $courseId = 0)
6521
{
6522
    $array = [];
6523
    $courseId = (int) $courseId;
6524
    $postId = (int) $postId;
6525
    if (empty($courseId)) {
6526
        // $courseId can be null, use api method
6527
        $courseId = api_get_course_int_id();
6528
    }
6529
    if ($courseId > 0) {
6530
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6531
        $sql = "SELECT id FROM $forumAttachmentTable
6532
                WHERE c_id = $courseId AND post_id = $postId";
6533
        $result = Database::query($sql);
6534
        if ($result !== false && Database::num_rows($result) > 0) {
6535
            while ($row = Database::fetch_array($result, 'ASSOC')) {
6536
                $array[] = $row['id'];
6537
            }
6538
        }
6539
    }
6540
6541
    return $array;
6542
}
6543
6544
/**
6545
 * Check if the forum category exists looking for its title.
6546
 *
6547
 * @param string $title     The forum category title
6548
 * @param int    $courseId  The course ID
6549
 * @param int    $sessionId Optional. The session ID
6550
 *
6551
 * @return bool
6552
 */
6553
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
6554
{
6555
    $sessionId = (int) $sessionId;
6556
    $courseId = (int) $courseId;
6557
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
6558
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
6559
6560
    $fakeFrom = "$forumCategoryTable fc
6561
        INNER JOIN $itemProperty ip ";
6562
6563
    if ($sessionId === 0) {
6564
        $fakeFrom .= "
6565
            ON (
6566
                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)
6567
            )
6568
        ";
6569
    } else {
6570
        $fakeFrom .= "
6571
            ON (
6572
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
6573
            )
6574
        ";
6575
    }
6576
6577
    $resultData = Database::select(
6578
        'fc.*',
6579
        $fakeFrom,
6580
        [
6581
            'where' => [
6582
                'ip.visibility != ? AND ' => 2,
6583
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
6584
                'fc.session_id = ? AND ' => $sessionId,
6585
                'fc.cat_title = ? AND ' => $title,
6586
                'fc.c_id = ?' => $courseId,
6587
            ],
6588
        ],
6589
        'first'
6590
    );
6591
6592
    if (empty($resultData)) {
6593
        return false;
6594
    }
6595
6596
    return $resultData;
6597
}
6598
6599
/**
6600
 * @param array $current_forum
6601
 * @param array $row
6602
 * @param bool  $addWrapper
6603
 *
6604
 * @return string
6605
 */
6606
function getPostStatus($current_forum, $row, $addWrapper = true)
6607
{
6608
    $statusIcon = '';
6609
    if ($current_forum['moderated']) {
6610
        if ($addWrapper) {
6611
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
6612
        }
6613
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
6614
6615
        $addUrl = false;
6616
        $showStatus = false;
6617
        if (api_is_allowed_to_edit(false, true)) {
6618
            $addUrl = true;
6619
        } else {
6620
            if ($row['user_id'] == api_get_user_id()) {
6621
                $showStatus = true;
6622
            }
6623
        }
6624
6625
        $label = '';
6626
        $icon = '';
6627
        $buttonType = '';
6628
        switch ($row['status']) {
6629
            case CForumPost::STATUS_VALIDATED:
6630
                $label = get_lang('Validated');
6631
                $icon = 'check-circle';
6632
                $buttonType = 'success';
6633
                break;
6634
            case CForumPost::STATUS_WAITING_MODERATION:
6635
                $label = get_lang('WaitingModeration');
6636
                $icon = 'warning';
6637
                $buttonType = 'warning';
6638
                break;
6639
            case CForumPost::STATUS_REJECTED:
6640
                $label = get_lang('Rejected');
6641
                $icon = 'minus-circle';
6642
                $buttonType = 'danger';
6643
                break;
6644
        }
6645
6646
        if ($addUrl) {
6647
            $statusIcon .= Display::toolbarButton(
6648
                $label.'&nbsp;',
6649
                'javascript:void(0)',
6650
                $icon,
6651
                $buttonType,
6652
                ['class' => 'change_post_status']
6653
            );
6654
        } else {
6655
            if ($showStatus) {
6656
                $statusIcon .= Display::label(
6657
                    Display::returnFontAwesomeIcon($icon).$label,
6658
                    $buttonType
6659
                );
6660
            }
6661
        }
6662
6663
        if ($addWrapper) {
6664
            $statusIcon .= '</span>';
6665
        }
6666
    }
6667
6668
    return $statusIcon;
6669
}
6670
6671
/**
6672
 * @param array $forumInfo
6673
 * @param int   $threadId
6674
 * @param int   $status
6675
 *
6676
 * @return mixed
6677
 */
6678
function getCountPostsWithStatus($status, $forumInfo, $threadId = null)
6679
{
6680
    $em = Database::getManager();
6681
    $criteria = Criteria::create();
6682
    $criteria
6683
        ->where(Criteria::expr()->eq('status', $status))
6684
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
6685
        ->andWhere(Criteria::expr()->eq('visible', 1))
6686
    ;
6687
6688
    if (!empty($threadId)) {
6689
        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
6690
    }
6691
6692
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
6693
    $qb->select('count(p.iid)')
6694
        ->addCriteria($criteria);
6695
6696
    return $qb->getQuery()->getSingleScalarResult();
6697
}
6698
6699
/**
6700
 * @param array $forum
6701
 * @param array $post
6702
 *
6703
 * @return bool
6704
 */
6705
function postIsEditableByStudent($forum, $post)
6706
{
6707
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6708
        return true;
6709
    }
6710
6711
    if ($forum['moderated'] == 1) {
6712
        if (is_null($post['status'])) {
6713
            return true;
6714
        } else {
6715
            return in_array(
6716
                $post['status'],
6717
                [
6718
                    CForumPost::STATUS_WAITING_MODERATION,
6719
                    CForumPost::STATUS_REJECTED,
6720
                ]
6721
            );
6722
        }
6723
    } else {
6724
        return true;
6725
    }
6726
}
6727
6728
/**
6729
 * @param int $postId
6730
 *
6731
 * @return bool
6732
 */
6733
function savePostRevision($postId)
6734
{
6735
    $postData = get_post_information($postId);
6736
6737
    if (empty($postData)) {
6738
        return false;
6739
    }
6740
6741
    $userId = api_get_user_id();
6742
6743
    if ($postData['poster_id'] != $userId) {
6744
        return false;
6745
    }
6746
6747
    $status = (int) !postNeedsRevision($postId);
6748
    $extraFieldValue = new ExtraFieldValue('forum_post');
6749
    $params = [
6750
        'item_id' => $postId,
6751
        'extra_ask_for_revision' => ['extra_ask_for_revision' => $status],
6752
    ];
6753
    if (empty($status)) {
6754
        unset($params['extra_ask_for_revision']);
6755
    }
6756
    $extraFieldValue->saveFieldValues(
6757
        $params,
6758
        true,
6759
        false,
6760
        ['ask_for_revision']
6761
    );
6762
}
6763
6764
/**
6765
 * @param int $postId
6766
 *
6767
 * @return string
6768
 */
6769
function getPostRevision($postId)
6770
{
6771
    $extraFieldValue = new ExtraFieldValue('forum_post');
6772
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6773
        $postId,
6774
        'revision_language'
6775
    );
6776
    $revision = '';
6777
    if ($value && isset($value['value'])) {
6778
        $revision = $value['value'];
6779
    }
6780
6781
    return $revision;
6782
}
6783
6784
/**
6785
 * @param int $postId
6786
 *
6787
 * @return bool
6788
 */
6789
function postNeedsRevision($postId)
6790
{
6791
    $extraFieldValue = new ExtraFieldValue('forum_post');
6792
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6793
        $postId,
6794
        'ask_for_revision'
6795
    );
6796
    $hasRevision = false;
6797
    if ($value && isset($value['value'])) {
6798
        return $value['value'] == 1;
6799
    }
6800
6801
    return $hasRevision;
6802
}
6803
6804
/**
6805
 * @param int   $postId
6806
 * @param array $threadInfo
6807
 *
6808
 * @return string
6809
 */
6810
function getAskRevisionButton($postId, $threadInfo)
6811
{
6812
    if (api_get_configuration_value('allow_forum_post_revisions') === false) {
6813
        return '';
6814
    }
6815
6816
    $postId = (int) $postId;
6817
6818
    $status = 'btn-default';
6819
    if (postNeedsRevision($postId)) {
6820
        $status = 'btn-success';
6821
    }
6822
6823
    return Display::url(
6824
        get_lang('AskRevision'),
6825
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6826
        api_get_cidreq().'&action=ask_revision&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6827
        ['class' => "btn $status", 'title' => get_lang('AskRevision')]
6828
    );
6829
}
6830
6831
/**
6832
 * @param int   $postId
6833
 * @param array $threadInfo
6834
 *
6835
 * @return string
6836
 */
6837
function giveRevisionButton($postId, $threadInfo)
6838
{
6839
    $postId = (int) $postId;
6840
6841
    return Display::toolbarButton(
6842
        get_lang('GiveRevision'),
6843
        api_get_path(WEB_CODE_PATH).'forum/reply.php?'.api_get_cidreq().'&'.http_build_query(
6844
            [
6845
                'forum' => $threadInfo['forum_id'],
6846
                'thread' => $threadInfo['thread_id'],
6847
                'post' => $postId = (int) $postId,
6848
                'action' => 'replymessage',
6849
                'give_revision' => 1,
6850
            ]
6851
        ),
6852
        'reply',
6853
        'primary',
6854
        ['id' => "reply-to-post-{$postId}"]
6855
    );
6856
}
6857
6858
/**
6859
 * @param int   $postId
6860
 * @param array $threadInfo
6861
 *
6862
 * @return string
6863
 */
6864
function getReportButton($postId, $threadInfo)
6865
{
6866
    $postId = (int) $postId;
6867
6868
    return Display::url(
6869
        Display::returnFontAwesomeIcon('flag'),
6870
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6871
        api_get_cidreq().'&action=report&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6872
        ['class' => 'btn btn-danger', 'title' => get_lang('Report')]
6873
    );
6874
}
6875
6876
/**
6877
 * @return bool
6878
 */
6879
function reportAvailable()
6880
{
6881
    $extraFieldValue = new ExtraFieldValue('course');
6882
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6883
        api_get_course_int_id(),
6884
        'allow_forum_report_button'
6885
    );
6886
    $allowReport = false;
6887
    if ($value && isset($value['value']) && $value['value'] == 1) {
6888
        $allowReport = true;
6889
    }
6890
6891
    return $allowReport;
6892
}
6893
6894
/**
6895
 * @return array
6896
 */
6897
function getReportRecipients()
6898
{
6899
    $extraFieldValue = new ExtraFieldValue('course');
6900
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6901
        api_get_course_int_id(),
6902
        'forum_report_recipients'
6903
    );
6904
    $users = [];
6905
    if ($value && isset($value['value'])) {
6906
        $usersType = explode(';', $value['value']);
6907
6908
        foreach ($usersType as $type) {
6909
            switch ($type) {
6910
                case 'teachers':
6911
                    $teachers = CourseManager::get_teacher_list_from_course_code(api_get_course_id());
6912
                    if (!empty($teachers)) {
6913
                        $users = array_merge($users, array_column($teachers, 'user_id'));
6914
                    }
6915
                break;
6916
                case 'admins':
6917
                    $admins = UserManager::get_all_administrators();
6918
                    if (!empty($admins)) {
6919
                        $users = array_merge($users, array_column($admins, 'user_id'));
6920
                    }
6921
                    break;
6922
                case 'community_managers':
6923
                    $managers = api_get_configuration_value('community_managers_user_list');
6924
                    if (!empty($managers) && isset($managers['users'])) {
6925
                        $users = array_merge($users, $managers['users']);
6926
                    }
6927
                    break;
6928
            }
6929
        }
6930
6931
        $users = array_unique(array_filter($users));
6932
    }
6933
6934
    return $users;
6935
}
6936
6937
/**
6938
 * @param int   $postId
6939
 * @param array $forumInfo
6940
 * @param array $threadInfo
6941
 *
6942
 * @return bool
6943
 */
6944
function reportPost($postId, $forumInfo, $threadInfo)
6945
{
6946
    if (!reportAvailable()) {
6947
        return false;
6948
    }
6949
6950
    if (empty($forumInfo) || empty($threadInfo)) {
6951
        return false;
6952
    }
6953
6954
    $postId = (int) $postId;
6955
6956
    $postData = get_post_information($postId);
6957
    $currentUser = api_get_user_info();
6958
6959
    if (!empty($postData)) {
6960
        $users = getReportRecipients();
6961
        if (!empty($users)) {
6962
            $url = api_get_path(WEB_CODE_PATH).
6963
                'forum/viewthread.php?forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'].'&'.api_get_cidreq().'&post_id='.$postId.'#post_id_'.$postId;
6964
            $postLink = Display::url(
6965
                $postData['post_title'],
6966
                $url
6967
            );
6968
            $subject = get_lang('ForumPostReported');
6969
            $content = sprintf(
6970
                get_lang('UserXReportedPostXInForumX'),
6971
                $currentUser['complete_name'],
6972
                $postLink,
6973
                $forumInfo['forum_title']
6974
            );
6975
            foreach ($users as $userId) {
6976
                MessageManager::send_message_simple($userId, $subject, $content);
6977
            }
6978
        }
6979
    }
6980
}
6981