Passed
Push — master ( 905664...dfb4c6 )
by Julito
09:06
created

show_edit_post_form()   C

Complexity

Conditions 11
Paths 96

Size

Total Lines 147
Code Lines 94

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 94
nc 96
nop 5
dl 0
loc 147
rs 5.9842
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CForumCategory;
8
use Chamilo\CourseBundle\Entity\CForumForum;
9
use Chamilo\CourseBundle\Entity\CForumPost;
10
use Chamilo\CourseBundle\Entity\CForumThread;
11
use ChamiloSession as Session;
12
use Doctrine\Common\Collections\Criteria;
13
14
/*
15
 * These files are a complete rework of the forum. The database structure is
16
 * based on phpBB but all the code is rewritten. A lot of new functionalities
17
 * are added:
18
 * - forum categories and forums can be sorted up or down, locked or made invisible
19
 * - consistent and integrated forum administration
20
 * - forum options:     are students allowed to edit their post?
21
 *                         moderation of posts (approval)
22
 *                         reply only forums (students cannot create new threads)
23
 *                         multiple forums per group
24
 * - sticky messages
25
 * - new view option: nested view
26
 * - quoting a message.
27
 *
28
 * @package chamilo.forum
29
 *
30
 * @todo convert into a class
31
 */
32
define('FORUM_NEW_POST', 0);
33
getNotificationsPerUser();
34
35
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
36
$htmlHeadXtra[] = '<script>
37
38
function check_unzip() {
39
    if (document.upload.unzip.checked){
40
        document.upload.if_exists[0].disabled=true;
41
        document.upload.if_exists[1].checked=true;
42
        document.upload.if_exists[2].disabled=true;
43
    } else {
44
        document.upload.if_exists[0].checked=true;
45
        document.upload.if_exists[0].disabled=false;
46
        document.upload.if_exists[2].disabled=false;
47
    }
48
}
49
function setFocus() {
50
    $("#title_file").focus();
51
}
52
</script>';
53
// The next javascript script is to manage ajax upload file
54
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
55
56
// Recover Thread ID, will be used to generate delete attachment URL to do ajax
57
$threadId = isset($_REQUEST['thread']) ? (int) ($_REQUEST['thread']) : 0;
58
$forumId = isset($_REQUEST['forum']) ? (int) ($_REQUEST['forum']) : 0;
59
60
$ajaxUrl = api_get_path(WEB_AJAX_PATH).'forum.ajax.php?'.api_get_cidreq();
61
// The next javascript script is to delete file by ajax
62
$htmlHeadXtra[] = '<script>
63
$(function () {
64
    $(document).on("click", ".deleteLink", function(e) {
65
        e.preventDefault();
66
        e.stopPropagation();
67
        var l = $(this);
68
        var id = l.closest("tr").attr("id");
69
        var filename = l.closest("tr").find(".attachFilename").html();
70
        if (confirm("'.get_lang('Are you sure to delete').'", filename)) {
71
            $.ajax({
72
                type: "POST",
73
                url: "'.$ajaxUrl.'&a=delete_file&attachId=" + id +"&thread='.$threadId.'&forum='.$forumId.'",
74
                dataType: "json",
75
                success: function(data) {
76
                    if (data.error == false) {
77
                        l.closest("tr").remove();
78
                        if ($(".files td").length < 1) {
79
                            $(".files").closest(".control-group").hide();
80
                        }
81
                    }
82
                }
83
            })
84
        }
85
    });
86
});
87
</script>';
88
89
/**
90
 * This function handles all the forum and forum categories actions. This is a wrapper for the
91
 * forum and forum categories. All this code code could go into the section where this function is
92
 * called but this make the code there cleaner.
93
 *
94
 * @param int $lp_id Learning path Id
95
 *
96
 * @author Patrick Cool <[email protected]>, Ghent University
97
 * @author Juan Carlos Raña Trabado (return to lp_id)
98
 *
99
 * @version may 2011, Chamilo 1.8.8
100
 */
101
function handle_forum_and_forumcategories($lp_id = null)
102
{
103
    $action_forum_cat = isset($_GET['action']) ? $_GET['action'] : '';
104
    $get_content = isset($_GET['content']) ? $_GET['content'] : '';
105
    $post_submit_cat = isset($_POST['SubmitForumCategory']) ? true : false;
106
    $post_submit_forum = isset($_POST['SubmitForum']) ? true : false;
107
    $get_id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
108
    $forum_categories_list = get_forum_categories();
109
110
    // Verify if forum category exists
111
    if (empty($forum_categories_list)) {
112
        $get_content = 'forumcategory';
113
    }
114
115
    $content = '';
116
117
    // Adding a forum category
118
    if (('add' === $action_forum_cat && 'forumcategory' === $get_content) || $post_submit_cat) {
119
        $content = show_add_forumcategory_form([], $lp_id); //$lp_id when is called from learning path
120
    }
121
122
    // Adding a forum
123
    if ((('add' === $action_forum_cat || 'edit' === $action_forum_cat) && 'forum' === $get_content) ||
124
        $post_submit_forum
125
    ) {
126
        $inputvalues = [];
127
        if ('edit' === $action_forum_cat && $get_id || $post_submit_forum) {
128
            $inputvalues = get_forums($get_id);
129
        }
130
        $content = show_add_forum_form($inputvalues, $lp_id);
131
    }
132
133
    // Edit a forum category
134
    if (('edit' === $action_forum_cat && 'forumcategory' === $get_content) ||
135
    (isset($_POST['SubmitEditForumCategory'])) ? true : false
136
    ) {
137
        $forum_category = get_forum_categories($get_id);
138
        $content = show_edit_forumcategory_form($forum_category);
139
    }
140
141
    // Delete a forum category
142
    if ('delete' === $action_forum_cat) {
143
        $list_threads = get_threads($get_id);
144
        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...
145
            deleteForumCategoryThread('thread', $list_threads[$i]['thread_id']);
146
            $link_info = GradebookUtils::isResourceInCourseGradebook(
147
                api_get_course_id(),
148
                5,
149
                $list_threads[$i]['thread_id'],
150
                api_get_session_id()
151
            );
152
            if (false !== $link_info) {
153
                GradebookUtils::remove_resource_from_course_gradebook($link_info['id']);
154
            }
155
        }
156
        deleteForumCategoryThread($get_content, $get_id);
157
    }
158
159
    // Change visibility of a forum or a forum category.
160
    if ('invisible' === $action_forum_cat || 'visible' === $action_forum_cat) {
161
        $return_message = change_visibility($get_content, $get_id, $action_forum_cat);
162
        Display::addFlash(
163
            Display::return_message($return_message, 'confirmation', false)
164
        );
165
    }
166
    // Change lock status of a forum or a forum category.
167
    if ('lock' === $action_forum_cat || 'unlock' === $action_forum_cat) {
168
        $return_message = change_lock_status($get_content, $get_id, $action_forum_cat);
169
        Display::addFlash(
170
            Display::return_message($return_message, 'confirmation', false)
171
        );
172
    }
173
    // Move a forum or a forum category.
174
    if ('move' === $action_forum_cat && isset($_GET['direction'])) {
175
        $return_message = move_up_down($get_content, $_GET['direction'], $get_id);
176
        Display::addFlash(
177
            Display::return_message($return_message, 'confirmation', false)
178
        );
179
    }
180
181
    return $content;
182
}
183
184
/**
185
 * This function displays the form that is used to add a forum category.
186
 *
187
 * @param array $inputvalues (deprecated, set to null when calling)
188
 * @param int   $lp_id       Learning path ID
189
 *
190
 * @return string
191
 *
192
 * @author Patrick Cool <[email protected]>, Ghent University
193
 * @author Juan Carlos Raña Trabado (return to lp_id)
194
 *
195
 * @version may 2011, Chamilo 1.8.8
196
 */
197
function show_add_forumcategory_form($inputvalues = [], $lp_id)
198
{
199
    $form = new FormValidator(
200
        'forumcategory',
201
        'post',
202
        'index.php?'.api_get_cidreq()
203
    );
204
    // hidden field if from learning path
205
    $form->addElement('hidden', 'lp_id', $lp_id);
206
    // Setting the form elements.
207
    $form->addElement('header', get_lang('Add forum category'));
208
    $form->addElement('text', 'forum_category_title', get_lang('Title'), ['autofocus']);
209
    $form->addElement(
210
        'html_editor',
211
        'forum_category_comment',
212
        get_lang('Description'),
213
        null,
214
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
215
    );
216
217
    $extraField = new ExtraField('forum_category');
218
    $returnParams = $extraField->addElements(
219
        $form,
220
        null,
221
        [], //exclude
222
        false, // filter
223
        false, // tag as select
224
        [], //show only fields
225
        [], // order fields
226
        [] // extra data
227
    );
228
229
    $form->addButtonCreate(get_lang('Create category'), 'SubmitForumCategory');
230
231
    // Setting the rules.
232
    $form->addRule('forum_category_title', get_lang('Required field'), 'required');
233
234
    // The validation or display
235
    if ($form->validate()) {
236
        $check = Security::check_token('post');
237
        if ($check) {
238
            $values = $form->exportValues();
239
            store_forumcategory($values);
240
        }
241
        Security::clear_token();
242
    } else {
243
        $token = Security::get_token();
244
        $form->addElement('hidden', 'sec_token');
245
        $form->setConstants(['sec_token' => $token]);
246
247
        return $form->returnForm();
248
    }
249
}
250
251
/**
252
 * This function displays the form that is used to add a forum category.
253
 *
254
 * @param array $inputvalues
255
 * @param int   $lp_id
256
 *
257
 * @author Patrick Cool <[email protected]>, Ghent University
258
 * @author Juan Carlos Raña Trabado (return to lp_id)
259
 *
260
 * @version may 2011, Chamilo 1.8.8
261
 */
262
function show_add_forum_form($inputvalues = [], $lp_id)
263
{
264
    $_course = api_get_course_info();
265
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq());
266
267
    // The header for the form
268
    $form_title = get_lang('Add a forum');
269
    if (!empty($inputvalues)) {
270
        $form_title = get_lang('Edit forum');
271
    }
272
273
    $form->addHeader($form_title);
274
275
    // We have a hidden field if we are editing.
276
    if (!empty($inputvalues) && is_array($inputvalues)) {
277
        $my_forum_id = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
278
        $form->addElement('hidden', 'forum_id', $my_forum_id);
279
    }
280
    $lp_id = (int) $lp_id;
281
282
    // hidden field if from learning path
283
    $form->addElement('hidden', 'lp_id', $lp_id);
284
285
    // The title of the forum
286
    $form->addElement('text', 'forum_title', get_lang('Title'), ['autofocus']);
287
288
    // The comment of the forum.
289
    $form->addElement(
290
        'html_editor',
291
        'forum_comment',
292
        get_lang('Description'),
293
        null,
294
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
295
    );
296
297
    // Dropdown list: Forum categories
298
    $forum_categories = get_forum_categories();
299
    $forum_categories_titles = [];
300
    foreach ($forum_categories as $value) {
301
        $forum_categories_titles[$value->getCatId()] = $value->getCatTitle();
302
    }
303
    $form->addElement(
304
        'select',
305
        'forum_category',
306
        get_lang('Create in category'),
307
        $forum_categories_titles
308
    );
309
    $form->applyFilter('forum_category', 'html_filter');
310
311
    if (COURSE_VISIBILITY_OPEN_WORLD == $_course['visibility']) {
312
        // This is for horizontal
313
        $group = [];
314
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('Yes'), 1);
315
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('No'), 0);
316
        $form->addGroup($group, 'allow_anonymous_group', get_lang('Allow anonymous posts?'));
317
    }
318
319
    $form->addButtonAdvancedSettings('advanced_params');
320
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
321
322
    $form->addDateTimePicker(
323
        'start_time',
324
        [get_lang('Public access (access authorized to any member of the course)ation date'), get_lang('Public access (access authorized to any member of the course)ation dateComment')],
325
        ['id' => 'start_time']
326
    );
327
328
    $form->addDateTimePicker(
329
        'end_time',
330
        [get_lang('Closing date'), get_lang('Closing dateComment')],
331
        ['id' => 'end_time']
332
    );
333
334
    $form->addRule(
335
        ['start_time', 'end_time'],
336
        get_lang('Start date must be before the end date'),
337
        'compare_datetime_text',
338
        '< allow_empty'
339
    );
340
341
    $group = [];
342
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('Yes'), 1);
343
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('No'), 0);
344
    $form->addGroup($group, 'moderated', get_lang('Moderated forum'));
345
346
    $group = [];
347
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('Yes'), 1);
348
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('No'), 0);
349
    $form->addGroup($group, 'students_can_edit_group', get_lang('Can learners edit their own posts?'));
350
351
    $group = [];
352
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Approval'), 1);
353
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Direct'), 0);
354
355
    $group = [];
356
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('Yes'), 1);
357
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('No'), 0);
358
359
    $group = [];
360
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('Yes'), 1);
361
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('No'), 0);
362
    $form->addGroup($group, 'allow_new_threads_group', get_lang('Allow users to start new threads'));
363
364
    $group = [];
365
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
366
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
367
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
368
    $form->addGroup($group, 'default_view_type_group', get_lang('Default view type'));
369
370
    // Drop down list: Groups
371
    $groups = GroupManager::get_group_list();
372
    $groups_titles[0] = get_lang('Not a group forum');
373
    foreach ($groups as $key => $value) {
374
        $groups_titles[$value['id']] = $value['name'];
375
    }
376
    $form->addElement('select', 'group_forum', get_lang('For Group'), $groups_titles);
377
378
    // Public or private group forum
379
    $group = [];
380
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Public access (access authorized to any member of the course)'), 'public');
381
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Private access (access authorized to group members only)'), 'private');
382
    $form->addGroup($group, 'public_private_group_forum_group', get_lang('Public access (access authorized to any member of the course)Private access (access authorized to group members only)GroupForum'));
383
384
    // Forum image
385
    $form->addProgress();
386
    if (!empty($inputvalues['forum_image'])) {
387
        $baseImagePath = api_get_course_path().'/upload/forum/images/'.$inputvalues['forum_image'];
388
        $image_path = api_get_path(WEB_COURSE_PATH).$baseImagePath;
389
        $sysImagePath = api_get_path(SYS_COURSE_PATH).$baseImagePath;
390
391
        if (file_exists($sysImagePath)) {
392
            $show_preview_image = Display::img(
393
                $image_path,
394
                null,
395
                ['class' => 'img-responsive']
396
            );
397
            $form->addElement('label', get_lang('Preview image'), $show_preview_image);
398
            $form->addElement('checkbox', 'remove_picture', null, get_lang('Remove picture'));
399
        }
400
    }
401
    $forum_image = isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
402
    $form->addElement('file', 'picture', ('' != $forum_image ? get_lang('Update Image') : get_lang('Add image')));
403
    $form->addRule(
404
        'picture',
405
        get_lang('Only PNG, JPG or GIF images allowed'),
406
        'filetype',
407
        ['jpg', 'jpeg', 'png', 'gif']
408
    );
409
410
    //$forumId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
411
    //$skillList = Skill::addSkillsToForm($form, ITEM_TYPE_FORUM, $forumId);
412
413
    $form->addElement('html', '</div>');
414
415
    // The OK button
416
    if (isset($_GET['id']) && 'edit' == $_GET['action']) {
417
        $form->addButtonUpdate(get_lang('Edit forum'), 'SubmitForum');
418
    } else {
419
        $form->addButtonCreate(get_lang('Create forum'), 'SubmitForum');
420
    }
421
422
    // setting the rules
423
    $form->addRule('forum_title', get_lang('Required field'), 'required');
424
    $form->addRule('forum_category', get_lang('Required field'), 'required');
425
426
    $defaultSettingAllowNewThreads = api_get_default_tool_setting('forum', 'allow_new_threads', 0);
427
428
    // Settings the defaults
429
    if (empty($inputvalues) || !is_array($inputvalues)) {
430
        $defaults['moderated']['moderated'] = 0;
431
        $defaults['allow_anonymous_group']['allow_anonymous'] = 0;
432
        $defaults['students_can_edit_group']['students_can_edit'] = 0;
433
        $defaults['approval_direct_group']['approval_direct'] = 0;
434
        $defaults['allow_attachments_group']['allow_attachments'] = 1;
435
        $defaults['allow_new_threads_group']['allow_new_threads'] = $defaultSettingAllowNewThreads;
436
        $defaults['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
437
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = 'public';
438
        if (isset($_GET['forumcategory'])) {
439
            $defaults['forum_category'] = Security::remove_XSS($_GET['forumcategory']);
440
        }
441
    } else {
442
        // the default values when editing = the data in the table
443
        $defaults['forum_id'] = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
444
        $defaults['forum_title'] = prepare4display(isset($inputvalues['forum_title']) ? $inputvalues['forum_title'] : null);
445
        $defaults['forum_comment'] = prepare4display(isset($inputvalues['forum_comment']) ? $inputvalues['forum_comment'] : null);
446
        $defaults['start_time'] = isset($inputvalues['start_time']) ? api_get_local_time($inputvalues['start_time']) : null;
447
        $defaults['end_time'] = isset($inputvalues['end_time']) ? api_get_local_time($inputvalues['end_time']) : null;
448
        $defaults['moderated']['moderated'] = isset($inputvalues['moderated']) ? $inputvalues['moderated'] : 0;
449
        $defaults['forum_category'] = isset($inputvalues['forum_category']) ? $inputvalues['forum_category'] : null;
450
        $defaults['allow_anonymous_group']['allow_anonymous'] = isset($inputvalues['allow_anonymous']) ? $inputvalues['allow_anonymous'] : null;
451
        $defaults['students_can_edit_group']['students_can_edit'] = isset($inputvalues['allow_edit']) ? $inputvalues['allow_edit'] : null;
452
        $defaults['approval_direct_group']['approval_direct'] = isset($inputvalues['approval_direct_post']) ? $inputvalues['approval_direct_post'] : null;
453
        $defaults['allow_attachments_group']['allow_attachments'] = isset($inputvalues['allow_attachments']) ? $inputvalues['allow_attachments'] : null;
454
        $defaults['allow_new_threads_group']['allow_new_threads'] = isset($inputvalues['allow_new_threads']) ? $inputvalues['allow_new_threads'] : $defaultSettingAllowNewThreads;
455
        $defaults['default_view_type_group']['default_view_type'] = isset($inputvalues['default_view']) ? $inputvalues['default_view'] : null;
456
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = isset($inputvalues['forum_group_public_private']) ? $inputvalues['forum_group_public_private'] : null;
457
        $defaults['group_forum'] = isset($inputvalues['forum_of_group']) ? $inputvalues['forum_of_group'] : null;
458
    }
459
460
    $form->setDefaults($defaults);
461
    // Validation or display
462
    if ($form->validate()) {
463
        $check = Security::check_token('post');
464
        if ($check) {
465
            $values = $form->getSubmitValues();
466
            $forumId = store_forum($values, '', true);
467
            if ($forumId) {
468
                // Skill::saveSkills($form, ITEM_TYPE_FORUM, $forumId);
469
                if (isset($values['forum_id'])) {
470
                    Display::addFlash(Display::return_message(get_lang('The forum has been modified'), 'confirmation'));
471
                } else {
472
                    Display::addFlash(Display::return_message(get_lang('The forum has been added'), 'confirmation'));
473
                }
474
            }
475
        }
476
        Security::clear_token();
477
    } else {
478
        $token = Security::get_token();
479
        $form->addElement('hidden', 'sec_token');
480
        $form->setConstants(['sec_token' => $token]);
481
482
        return $form->returnForm();
483
    }
484
}
485
486
/**
487
 * This function deletes the forum image if exists.
488
 *
489
 * @param int $forum_id forum id
490
 *
491
 * @return bool true if success
492
 *
493
 * @author Julio Montoya <[email protected]>
494
 *
495
 * @version february 2006, dokeos 1.8
496
 */
497
function delete_forum_image($forum_id)
498
{
499
    $table_forums = Database::get_course_table(TABLE_FORUM);
500
    $course_id = api_get_course_int_id();
501
    $forum_id = (int) $forum_id;
502
503
    $sql = "SELECT forum_image FROM $table_forums
504
            WHERE forum_id = $forum_id AND c_id = $course_id";
505
    $result = Database::query($sql);
506
    $row = Database::fetch_array($result);
507
    if ('' != $row['forum_image']) {
508
        $file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
509
        if (file_exists($file)) {
510
            unlink($file);
511
        }
512
513
        return true;
514
    } else {
515
        return false;
516
    }
517
}
518
519
/**
520
 * This function displays the form that is used to edit a forum category.
521
 *
522
 * @param array $inputvalues
523
 *
524
 * @return string
525
 *
526
 * @author Patrick Cool <[email protected]>, Ghent University
527
 *
528
 * @version february 2006, dokeos 1.8
529
 */
530
function show_edit_forumcategory_form($inputvalues = [])
531
{
532
    $categoryId = $inputvalues['cat_id'];
533
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq().'&id='.$categoryId);
534
535
    // Setting the form elements.
536
    $form->addElement('header', '', get_lang('Edit forumCategory'));
537
    $form->addElement('hidden', 'forum_category_id');
538
    $form->addElement('text', 'forum_category_title', get_lang('Title'));
539
540
    $form->addElement(
541
        'html_editor',
542
        'forum_category_comment',
543
        get_lang('Comment'),
544
        null,
545
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
546
    );
547
548
    $extraField = new ExtraField('forum_category');
549
    $returnParams = $extraField->addElements(
550
        $form,
551
        $categoryId,
552
        [], //exclude
553
        false, // filter
554
        false, // tag as select
555
        [], //show only fields
556
        [], // order fields
557
        [] // extra data
558
    );
559
560
    $form->addButtonUpdate(get_lang('Edit category'), 'SubmitEdit forumCategory');
561
562
    // Setting the default values.
563
    $defaultvalues['forum_category_id'] = $inputvalues['cat_id'];
564
    $defaultvalues['forum_category_title'] = $inputvalues['cat_title'];
565
    $defaultvalues['forum_category_comment'] = $inputvalues['cat_comment'];
566
    $form->setDefaults($defaultvalues);
567
568
    // Setting the rules.
569
    $form->addRule('forum_category_title', get_lang('Required field'), 'required');
570
571
    // Validation or display
572
    if ($form->validate()) {
573
        $check = Security::check_token('post');
574
        if ($check) {
575
            $values = $form->exportValues();
576
            store_forumcategory($values);
577
        }
578
        Security::clear_token();
579
    } else {
580
        $token = Security::get_token();
581
        $form->addElement('hidden', 'sec_token');
582
        $form->setConstants(['sec_token' => $token]);
583
584
        return $form->returnForm();
585
    }
586
}
587
588
/**
589
 * This function stores the forum category in the database.
590
 * The new category is added to the end.
591
 *
592
 * @param array $values
593
 * @param array $courseInfo
594
 * @param bool  $showMessage
595
 */
596
function store_forumcategory($values, $courseInfo = [], $showMessage = true)
597
{
598
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
599
    $course_id = $courseInfo['real_id'];
600
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
601
602
    // Find the max cat_order. The new forum category is added at the end => max cat_order + &
603
    $sql = "SELECT MAX(cat_order) as sort_max
604
            FROM $table_categories
605
            WHERE c_id = $course_id";
606
    $result = Database::query($sql);
607
    $row = Database::fetch_array($result);
608
    $new_max = $row['sort_max'] + 1;
609
    $session_id = api_get_session_id();
610
    $clean_cat_title = $values['forum_category_title'];
611
    $last_id = null;
612
613
    $repo = Container::getForumCategoryRepository();
614
615
    if (isset($values['forum_category_id'])) {
616
        // Storing after edition.
617
        $params = [
618
            'cat_title' => $clean_cat_title,
619
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
620
        ];
621
622
        Database::update(
623
            $table_categories,
624
            $params,
625
            [
626
                'c_id = ? AND cat_id = ?' => [
627
                    $course_id,
628
                    $values['forum_category_id'],
629
                ],
630
            ]
631
        );
632
633
        api_item_property_update(
634
            $courseInfo,
635
            TOOL_FORUM_CATEGORY,
636
            $values['forum_category_id'],
637
            'ForumCategoryUpdated',
638
            api_get_user_id()
639
        );
640
        $return_message = get_lang('The forum category has been modified');
641
642
        $logInfo = [
643
            'tool' => TOOL_FORUM,
644
            'tool_id' => 0,
645
            'tool_id_detail' => 0,
646
            'action' => 'update-forumcategory',
647
            'action_details' => 'forumcategory',
648
            'info' => $clean_cat_title,
649
        ];
650
        Event::registerLog($logInfo);
651
652
        $values['item_id'] = $values['forum_category_id'];
653
    } else {
654
        $category = new CForumCategory();
655
        $category
656
            ->setCatTitle($clean_cat_title)
657
            ->setCatComment(isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '')
658
            ->setCatOrder($new_max)
659
            ->setCId($course_id)
660
            ->setSessionId($session_id)
661
        ;
662
        $user = api_get_user_entity(api_get_user_id());
663
        $course = api_get_course_entity($course_id);
664
        $session = api_get_session_entity($session_id);
665
666
        $repo->addResourceToCourse($category, ResourceLink::VISIBILITY_PUBLISHED, $user, $course, $session);
667
        $repo->getEntityManager()->persist($category);
668
        $repo->getEntityManager()->flush();
669
670
        $last_id = $category->getIid();
671
672
        if ($last_id > 0) {
673
            $sql = "UPDATE $table_categories SET cat_id = $last_id WHERE iid = $last_id";
674
            Database::query($sql);
675
676
            /*api_item_property_update(
677
                $courseInfo,
678
                TOOL_FORUM_CATEGORY,
679
                $last_id,
680
                'ForumCategoryAdded',
681
                api_get_user_id()
682
            );
683
            api_set_default_visibility(
684
                $last_id,
685
                TOOL_FORUM_CATEGORY,
686
                0,
687
                $courseInfo
688
            );*/
689
        }
690
        $return_message = get_lang('The forum category has been added');
691
692
        $logInfo = [
693
            'tool' => TOOL_FORUM,
694
            'tool_id' => 0,
695
            'tool_id_detail' => 0,
696
            'action' => 'new-forumcategory',
697
            'action_details' => 'forumcategory',
698
            'info' => $clean_cat_title,
699
        ];
700
        Event::registerLog($logInfo);
701
702
        $values['item_id'] = $last_id;
703
    }
704
705
    $extraFieldValue = new ExtraFieldValue('forum_category');
706
    $extraFieldValue->saveFieldValues($values);
707
708
    if ($showMessage) {
709
        Display::addFlash(Display::return_message($return_message, 'confirmation'));
710
    }
711
712
    return $last_id;
713
}
714
715
/**
716
 * This function stores the forum in the database. The new forum is added to the end.
717
 *
718
 * @param array $values
719
 * @param array $courseInfo
720
 * @param bool  $returnId
721
 *
722
 * @return string language variable
723
 */
724
function store_forum($values, $courseInfo = [], $returnId = false)
725
{
726
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
727
    $courseId = $courseInfo['real_id'];
728
    $session_id = api_get_session_id();
729
    $group_id = api_get_group_id();
730
    if (isset($values['group_id']) && !empty($values['group_id'])) {
731
        $group_id = $values['group_id'];
732
    }
733
    $groupInfo = [];
734
    if (!empty($group_id)) {
735
        $groupInfo = GroupManager::get_group_properties($group_id);
736
    }
737
738
    $table_forums = Database::get_course_table(TABLE_FORUM);
739
740
    // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
741
    if (null === $values['forum_category']) {
742
        $new_max = null;
743
    } else {
744
        $sql = "SELECT MAX(forum_order) as sort_max
745
                FROM $table_forums
746
                WHERE
747
                    c_id = $courseId AND
748
                    forum_category='".Database::escape_string($values['forum_category'])."'";
749
        $result = Database::query($sql);
750
        $row = Database::fetch_array($result);
751
        $new_max = $row['sort_max'] + 1;
752
    }
753
754
    // Forum images
755
    $has_attachment = false;
756
    $image_moved = true;
757
    if (!empty($_FILES['picture']['name'])) {
758
        $upload_ok = process_uploaded_file($_FILES['picture']);
759
        $has_attachment = true;
760
    }
761
762
    // Remove existing picture if it was requested.
763
    if (!empty($_POST['remove_picture'])) {
764
        delete_forum_image($values['forum_id']);
765
    }
766
767
    $new_file_name = '';
768
    if (isset($upload_ok)) {
769
        if ($has_attachment) {
770
            $course_dir = $courseInfo['path'].'/upload/forum/images';
771
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
772
            $updir = $sys_course_path.$course_dir;
773
            // Try to add an extension to the file if it hasn't one.
774
            $new_file_name = add_ext_on_mime(
775
                Database::escape_string($_FILES['picture']['name']),
776
                $_FILES['picture']['type']
777
            );
778
            if (!filter_extension($new_file_name)) {
779
                //Display::addFlash(Display::return_message(get_lang('File upload failed: this file extension or file type is prohibited'), 'error'));
780
                $image_moved = false;
781
            } else {
782
                $file_extension = explode('.', $_FILES['picture']['name']);
783
                $file_extension = strtolower($file_extension[count($file_extension) - 1]);
784
                $new_file_name = uniqid('').'.'.$file_extension;
785
                $new_path = $updir.'/'.$new_file_name;
786
                $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
787
                // Storing the attachments if any
788
                if ($result) {
789
                    $image_moved = true;
790
                }
791
            }
792
        }
793
    }
794
795
    $repo = Container::getForumRepository();
796
797
    if (!isset($values['forum_id'])) {
798
        $forum = new CForumForum();
799
        $forum
800
            ->setCId($courseId)
801
            ->setSessionId($session_id)
802
            ->setForumOrder(isset($new_max) ? $new_max : null)
803
        ;
804
    } else {
805
        $forum = $repo->find($values['forum_id']);
806
    }
807
808
    $forumCategory = null;
809
    if (!empty($values['forum_category'])) {
810
        $repoForumCategory = Container::getForumCategoryRepository();
811
        $forumCategory = $repoForumCategory->find($values['forum_category']);
812
    }
813
    //'forum_image' => $new_file_name,
814
    $forum
815
        ->setForumTitle($values['forum_title'])
816
        ->setForumComment($values['forum_comment'] ?? null)
817
        ->setForumCategory($forumCategory)
818
        ->setAllowAnonymous($values['allow_anonymous_group']['allow_anonymous'] ?? null)
819
        ->setAllowEdit($values['students_can_edit_group']['students_can_edit'] ?? null)
820
        ->setApprovalDirectPost($values['approval_direct_group']['approval_direct'] ?? null)
821
        ->setAllowAttachments($values['allow_attachments_group']['allow_attachments'] ?? null)
822
        ->setAllowNewThreads($values['allow_new_threads_group']['allow_new_threads'] ?? null)
823
        ->setDefaultView($values['default_view_type_group']['default_view_type'] ?? null)
824
        ->setForumOfGroup($values['group_forum'] ?? null)
825
        ->setForumGroupPublicPrivate($values['public_private_group_forum_group']['public_private_group_forum'] ?? '')
826
        ->setModerated($values['moderated']['moderated'] ?? null)
827
        ->setStartTime(!empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null)
828
        ->setEndTime(!empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null)
829
        ->setSessionId($session_id)
830
        ->setLpId($values['lp_id'] ?? 0)
831
832
    ;
833
834
    $user = api_get_user_entity(api_get_user_id());
835
    $course = api_get_course_entity($courseId);
836
    $session = api_get_session_entity($session_id);
837
838
    if (isset($values['forum_id'])) {
839
        // Edit
840
        $repo->getEntityManager()->persist($forum);
841
        $repo->getEntityManager()->flush();
842
843
        if (isset($upload_ok)) {
844
            if ($has_attachment) {
845
                //$params['forum_image'] = $new_file_name;
846
            }
847
        }
848
849
        if (isset($values['remove_picture']) && 1 == $values['remove_picture']) {
850
            /*$params['forum_image'] = '';
851
            delete_forum_image($values['forum_id']);*/
852
        }
853
854
        // Move groups from one group to another
855
        if (isset($values['group_forum']) && false) {
856
            $forumData = get_forums($values['forum_id']);
857
            $currentGroupId = $forumData['forum_of_group'];
858
            if ($currentGroupId != $values['group_forum']) {
859
                $threads = get_threads($values['forum_id']);
860
                $toGroupId = 'NULL';
861
                if (!empty($values['group_forum'])) {
862
                    $toGroupId = $values['group_forum'];
863
                }
864
                $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
865
                foreach ($threads as $thread) {
866
                    $sql = "UPDATE $tableItemProperty
867
                            SET to_group_id = $toGroupId
868
                            WHERE
869
                                tool = '".TOOL_FORUM_THREAD."' AND
870
                                ref = ".$thread['thread_id'].' AND
871
                                c_id = '.$courseId;
872
                    Database::query($sql);
873
874
                    $posts = getPosts(
875
                        $forumData,
876
                        $thread['thread_id']
877
                    );
878
879
                    foreach ($posts as $post) {
880
                        $postId = $post['post_id'];
881
                        $attachMentList = getAllAttachment($postId);
882
                        if (!empty($attachMentList)) {
883
                            foreach ($attachMentList as $attachMent) {
884
                                $sql = "UPDATE $tableItemProperty
885
                                        SET to_group_id = $toGroupId
886
                                        WHERE
887
                                            tool = '".TOOL_FORUM_ATTACH."' AND
888
                                            ref = ".$attachMent['iid'].' AND
889
                                            c_id = '.$courseId;
890
                                Database::query($sql);
891
                            }
892
                        }
893
894
                        $sql = "UPDATE $tableItemProperty
895
                                SET to_group_id = $toGroupId
896
                                WHERE
897
                                    tool = '".TOOL_FORUM_POST."' AND
898
                                    ref = $postId AND
899
                                    c_id = $courseId";
900
                        Database::query($sql);
901
                    }
902
                }
903
            }
904
        }
905
906
        /*
907
        api_item_property_update(
908
            $courseInfo,
909
            TOOL_FORUM,
910
            Database::escape_string($values['forum_id']),
911
            'ForumUpdated',
912
            api_get_user_id(),
913
            $groupInfo
914
        );*/
915
916
        $return_message = get_lang('The forum has been modified');
917
        $forumId = $forum->getIid();
918
919
        $logInfo = [
920
            'tool' => TOOL_FORUM,
921
            'tool_id' => $values['forum_id'],
922
            'action' => 'update-forum',
923
            'action_details' => 'forum',
924
            'info' => $values['forum_title'],
925
        ];
926
        Event::registerLog($logInfo);
927
    } else {
928
        if ($image_moved) {
929
            $new_file_name = isset($new_file_name) ? $new_file_name : '';
930
        }
931
932
        $repo->addResourceToCourse($forum, ResourceLink::VISIBILITY_PUBLISHED, $user, $course, $session);
933
        $repo->getEntityManager()->persist($forum);
934
        $repo->getEntityManager()->flush();
935
936
        $forumId = $forum->getIid();
937
        if ($forumId > 0) {
938
            $sql = "UPDATE $table_forums SET forum_id = iid WHERE iid = $forumId";
939
            Database::query($sql);
940
            $courseCode = $courseInfo['code'];
941
            $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications');
942
943
            $status = STUDENT;
944
            if (!empty($session_id)) {
945
                $status = 0;
946
            }
947
            if (1 === $subscribe) {
948
                $userList = CourseManager::get_user_list_from_course_code(
949
                    $courseCode,
950
                    $session_id,
951
                    null,
952
                    null,
953
                    $status
954
                );
955
                foreach ($userList as $userInfo) {
956
                    set_notification('forum', $forumId, false, $userInfo, $courseInfo);
957
                }
958
            }
959
960
            /*api_item_property_update(
961
                $courseInfo,
962
                TOOL_FORUM,
963
                $forumId,
964
                'ForumAdded',
965
                api_get_user_id(),
966
                $groupInfo
967
            );
968
969
            api_set_default_visibility(
970
                $forumId,
971
                TOOL_FORUM,
972
                $group_id,
973
                $courseInfo
974
            );*/
975
976
            $logInfo = [
977
                'tool' => TOOL_FORUM,
978
                'tool_id' => $forumId,
979
                'action' => 'new-forum',
980
                'action_details' => 'forum',
981
                'info' => $values['forum_title'],
982
            ];
983
            Event::registerLog($logInfo);
984
        }
985
        $return_message = get_lang('The forum has been added');
986
    }
987
988
    if ($returnId) {
989
        return $forumId;
990
    }
991
992
    return $return_message;
993
}
994
995
/**
996
 * This function deletes a forum or a forum category
997
 * This function currently does not delete the forums inside the category,
998
 * nor the threads and replies inside these forums.
999
 * For the moment this is the easiest method and it has the advantage that it
1000
 * allows to recover fora that were acidently deleted
1001
 * when the forum category got deleted.
1002
 *
1003
 * @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...
1004
 * @param the $id id of the forum category that has to be deleted
1005
 *
1006
 * @todo write the code for the cascading deletion of the forums inside a
1007
 * forum category and also the threads and replies inside these forums
1008
 * @todo config setting for recovery or not
1009
 * (see also the documents tool: real delete or not).
1010
 *
1011
 * @return string
1012
 *
1013
 * @author Patrick Cool <[email protected]>, Ghent University
1014
 *
1015
 * @version february 2006, dokeos 1.8
1016
 */
1017
function deleteForumCategoryThread($content, $id)
1018
{
1019
    $_course = api_get_course_info();
1020
    $table_forums = Database::get_course_table(TABLE_FORUM);
1021
    $table_forums_post = Database::get_course_table(TABLE_FORUM_POST);
1022
    $table_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
1023
    $course_id = api_get_course_int_id();
1024
    $groupId = api_get_group_id();
1025
    $groupInfo = GroupManager::get_group_properties($groupId);
1026
    $userId = api_get_user_id();
1027
    $id = (int) $id;
1028
1029
    // Delete all attachment file about this tread id.
1030
    $sql = "SELECT post_id FROM $table_forums_post
1031
            WHERE c_id = $course_id AND thread_id = '".$id."' ";
1032
    $res = Database::query($sql);
1033
    while ($poster_id = Database::fetch_row($res)) {
1034
        delete_attachment($poster_id[0]);
1035
    }
1036
1037
    $tool_constant = null;
1038
    $return_message = '';
1039
    if ('forumcategory' === $content) {
1040
        $tool_constant = TOOL_FORUM_CATEGORY;
1041
        $return_message = get_lang('Forum category deleted');
1042
1043
        if (!empty($forum_list)) {
1044
            $sql = "SELECT forum_id FROM $table_forums
1045
                    WHERE c_id = $course_id AND forum_category='".$id."'";
1046
            $result = Database::query($sql);
1047
            $row = Database::fetch_array($result);
1048
            foreach ($row as $arr_forum) {
1049
                $forum_id = $arr_forum['forum_id'];
1050
                api_item_property_update(
1051
                    $_course,
1052
                    'forum',
1053
                    $forum_id,
1054
                    'delete',
1055
                    api_get_user_id()
1056
                );
1057
            }
1058
        }
1059
    }
1060
1061
    if ('forum' === $content) {
1062
        $tool_constant = TOOL_FORUM;
1063
        $return_message = get_lang('Forum deleted');
1064
1065
        if (!empty($number_threads)) {
1066
            $sql = "SELECT thread_id FROM $table_forum_thread
1067
                    WHERE c_id = $course_id AND forum_id = $id ";
1068
            $result = Database::query($sql);
1069
            $row = Database::fetch_array($result);
1070
            foreach ($row as $arr_forum) {
1071
                $forum_id = $arr_forum['thread_id'];
1072
                api_item_property_update(
1073
                    $_course,
1074
                    'forum_thread',
1075
                    $forum_id,
1076
                    'delete',
1077
                    api_get_user_id()
1078
                );
1079
            }
1080
        }
1081
    }
1082
1083
    if ('thread' === $content) {
1084
        $tool_constant = TOOL_FORUM_THREAD;
1085
        $return_message = get_lang('Thread deleted');
1086
        Skill::deleteSkillsFromItem($id, ITEM_TYPE_FORUM_THREAD);
1087
    }
1088
1089
    api_item_property_update(
1090
        $_course,
1091
        $tool_constant,
1092
        $id,
1093
        'delete',
1094
        $userId,
1095
        $groupInfo
1096
    );
1097
1098
    // Check if this returns a true and if so => return $return_message, if not => return false;
1099
    if (!empty($return_message)) {
1100
        Display::addFlash(Display::return_message($return_message, 'confirmation', false));
1101
    }
1102
1103
    return $return_message;
1104
}
1105
1106
/**
1107
 * This function deletes a forum post. This separate function is needed because forum posts do not appear
1108
 * in the item_property table (yet)
1109
 * and because deleting a post also has consequence on the posts that have this post as parent_id
1110
 * (they are also deleted).
1111
 * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
1112
 * We also have to decrease the number of replies in the thread table.
1113
 *
1114
 * @param the $post_id id of the post that will be deleted
1115
 *
1116
 * @todo write recursive function that deletes all the posts that have this message as parent
1117
 *
1118
 * @return string language variable
1119
 *
1120
 * @author Patrick Cool <[email protected]>, Ghent University
1121
 * @author Hubert Borderiou Function cleanead and fixed
1122
 *
1123
 * @version february 2006
1124
 */
1125
function delete_post($post_id)
1126
{
1127
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1128
    $post_id = (int) $post_id;
1129
    $course_id = api_get_course_int_id();
1130
    $em = Database::getManager();
1131
1132
    $post = $em
1133
        ->getRepository('ChamiloCourseBundle:CForumPost')
1134
        ->findOneBy(['cId' => $course_id, 'postId' => $post_id]);
1135
1136
    if ($post) {
1137
        $em
1138
            ->createQuery('
1139
                UPDATE ChamiloCourseBundle:CForumPost p
1140
                SET p.postParentId = :parent_of_deleted_post
1141
                WHERE
1142
                    p.cId = :course AND
1143
                    p.postParentId = :post AND
1144
                    p.threadId = :thread_of_deleted_post AND
1145
                    p.forumId = :forum_of_deleted_post
1146
            ')
1147
            ->execute([
1148
                'parent_of_deleted_post' => $post->getPostParentId(),
1149
                'course' => $course_id,
1150
                'post' => $post->getPostId(),
1151
                'thread_of_deleted_post' => $post->getThread() ? $post->getThread()->getIid() : 0,
1152
                'forum_of_deleted_post' => $post->getForumId(),
1153
            ]);
1154
1155
        $em->remove($post);
1156
        $em->flush();
1157
1158
        // Delete attachment file about this post id.
1159
        delete_attachment($post_id);
1160
    }
1161
1162
    $last_post_of_thread = check_if_last_post_of_thread($_GET['thread']);
1163
1164
    if (is_array($last_post_of_thread)) {
1165
        // Decreasing the number of replies for this thread and also changing the last post information.
1166
        $sql = "UPDATE $table_threads
1167
                SET
1168
                    thread_replies = thread_replies - 1,
1169
                    thread_last_post = ".(int) ($last_post_of_thread['post_id']).",
1170
                    thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
1171
                WHERE c_id = $course_id AND thread_id = ".(int) ($_GET['thread']);
1172
        Database::query($sql);
1173
1174
        return 'PostDeleted';
1175
    }
1176
    if (!$last_post_of_thread) {
1177
        // We deleted the very single post of the thread so we need to delete the entry in the thread table also.
1178
        $sql = "DELETE FROM $table_threads
1179
                WHERE c_id = $course_id AND thread_id = ".(int) ($_GET['thread']);
1180
        Database::query($sql);
1181
1182
        return 'PostDeletedSpecial';
1183
    }
1184
}
1185
1186
/**
1187
 * This function gets the all information of the last (=most recent) post of the thread
1188
 * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date.
1189
 *
1190
 * @param the $thread_id id of the thread we want to know the last post of
1191
 *
1192
 * @return an array or bool if there is a last post found, false if there is
1193
 *            no post entry linked to that thread => thread will be deleted
1194
 *
1195
 * @author Patrick Cool <[email protected]>, Ghent University
1196
 *
1197
 * @version february 2006, dokeos 1.8
1198
 */
1199
function check_if_last_post_of_thread($thread_id)
1200
{
1201
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1202
    $course_id = api_get_course_int_id();
1203
    $sql = "SELECT * FROM $table_posts
1204
            WHERE c_id = $course_id AND thread_id = ".(int) $thread_id.'
1205
            ORDER BY post_date DESC';
1206
    $result = Database::query($sql);
1207
    if (Database::num_rows($result) > 0) {
1208
        return Database::fetch_array($result);
1209
    } else {
1210
        return false;
1211
    }
1212
}
1213
1214
/**
1215
 * @param string $content                   Type of content forum category, forum, thread, post
1216
 * @param int    $id                        the id of the content we want to make invisible
1217
 * @param int    $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
1218
 * @param array  $additional_url_parameters
1219
 *
1220
 * @return string HTML
1221
 */
1222
function return_visible_invisible_icon(
1223
    $content,
1224
    $id,
1225
    $current_visibility_status,
1226
    $additional_url_parameters = ''
1227
) {
1228
    $html = '';
1229
    $id = (int) $id;
1230
1231
    if ($current_visibility_status) {
1232
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1233
        if (is_array($additional_url_parameters)) {
1234
            foreach ($additional_url_parameters as $key => $value) {
1235
                $html .= $key.'='.$value.'&';
1236
            }
1237
        }
1238
        $html .= 'action=invisible&content='.$content.'&id='.$id.'">'.
1239
            Display::return_icon('visible.png', get_lang('Make invisible'), [], ICON_SIZE_SMALL).'</a>';
1240
    } else {
1241
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1242
        if (is_array($additional_url_parameters)) {
1243
            foreach ($additional_url_parameters as $key => $value) {
1244
                $html .= $key.'='.$value.'&';
1245
            }
1246
        }
1247
        $html .= 'action=visible&content='.$content.'&id='.$id.'">'.
1248
            Display::return_icon('invisible.png', get_lang('Make Visible'), [], ICON_SIZE_SMALL).'</a>';
1249
    }
1250
1251
    return $html;
1252
}
1253
1254
/**
1255
 * @param $content
1256
 * @param $id
1257
 * @param $current_lock_status
1258
 * @param string $additional_url_parameters
1259
 *
1260
 * @return string
1261
 */
1262
function return_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters = '')
1263
{
1264
    $html = '';
1265
    $id = (int) $id;
1266
    //check if the forum is blocked due
1267
    if ('thread' == $content) {
1268
        if (api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD)) {
1269
            return $html.Display::return_icon(
1270
                'lock_na.png',
1271
                get_lang('This option is not available because this activity is contained by an assessment, which is currently locked. To unlock the assessment, ask your platform administrator.'),
1272
                [],
1273
                ICON_SIZE_SMALL
1274
            );
1275
        }
1276
    }
1277
    if ('1' == $current_lock_status) {
1278
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1279
        if (is_array($additional_url_parameters)) {
1280
            foreach ($additional_url_parameters as $key => $value) {
1281
                $html .= $key.'='.$value.'&';
1282
            }
1283
        }
1284
        $html .= 'action=unlock&content='.$content.'&id='.$id.'">'.
1285
            Display::return_icon('lock.png', get_lang('Unlock'), [], ICON_SIZE_SMALL).'</a>';
1286
    }
1287
    if ('0' == $current_lock_status) {
1288
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1289
        if (is_array($additional_url_parameters)) {
1290
            foreach ($additional_url_parameters as $key => $value) {
1291
                $html .= $key.'='.$value.'&';
1292
            }
1293
        }
1294
        $html .= 'action=lock&content='.$content.'&id='.$id.'">'.
1295
            Display::return_icon('unlock.png', get_lang('Lock'), [], ICON_SIZE_SMALL).'</a>';
1296
    }
1297
1298
    return $html;
1299
}
1300
1301
/**
1302
 * This function takes care of the display of the up and down icon.
1303
 *
1304
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1305
 * @param int    $id      is the id of the item we want to display the icons for
1306
 * @param array  $list    is an array of all the items. All items in this list should have
1307
 *                        an up and down icon except for the first (no up icon) and the last (no down icon)
1308
 *                        The key of this $list array is the id of the item.
1309
 *
1310
 * @return string HTML
1311
 */
1312
function return_up_down_icon($content, $id, $list)
1313
{
1314
    $id = (int) $id;
1315
    $total_items = count($list);
1316
    $position = 0;
1317
    $internal_counter = 0;
1318
    $forumCategory = isset($_GET['forumcategory']) ? Security::remove_XSS($_GET['forumcategory']) : null;
1319
1320
    if (is_array($list)) {
1321
        foreach ($list as $key => $listitem) {
1322
            $internal_counter++;
1323
            if ($id == $key) {
1324
                $position = $internal_counter;
1325
            }
1326
        }
1327
    }
1328
1329
    if ($position > 1) {
1330
        $return_value = '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=up&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('Move up').'">'.
1331
            Display::return_icon('up.png', get_lang('Move up'), [], ICON_SIZE_SMALL).'</a>';
1332
    } else {
1333
        $return_value = Display::return_icon('up_na.png', '-', [], ICON_SIZE_SMALL);
1334
    }
1335
1336
    if ($position < $total_items) {
1337
        $return_value .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=down&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('Move down').'" >'.
1338
            Display::return_icon('down.png', get_lang('Move down'), [], ICON_SIZE_SMALL).'</a>';
1339
    } else {
1340
        $return_value .= Display::return_icon('down_na.png', '-', [], ICON_SIZE_SMALL);
1341
    }
1342
1343
    return $return_value;
1344
}
1345
1346
/**
1347
 * This function changes the visibility in the database (item_property).
1348
 *
1349
 * @param string $content           what is it that we want to make (in)visible: forum category, forum, thread, post
1350
 * @param int    $id                the id of the content we want to make invisible
1351
 * @param string $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
1352
 *
1353
 * @todo change the get parameter so that it matches the tool constants.
1354
 * @todo check if api_item_property_update returns true or false => returnmessage depends on it.
1355
 * @todo move to itemmanager
1356
 *
1357
 * @return string language variable
1358
 *
1359
 * @author Patrick Cool <[email protected]>, Ghent University
1360
 *
1361
 * @version february 2006, dokeos 1.8
1362
 */
1363
function change_visibility($content, $id, $target_visibility)
1364
{
1365
    $_course = api_get_course_info();
1366
    $constants = [
1367
        'forumcategory' => TOOL_FORUM_CATEGORY,
1368
        'forum' => TOOL_FORUM,
1369
        'thread' => TOOL_FORUM_THREAD,
1370
    ];
1371
    api_item_property_update(
1372
        $_course,
1373
        $constants[$content],
1374
        $id,
1375
        $target_visibility,
1376
        api_get_user_id()
1377
    );
1378
1379
    if ('visible' == $target_visibility) {
1380
        handle_mail_cue($content, $id);
1381
    }
1382
1383
    return get_lang('The visibility has been changed.');
1384
}
1385
1386
/**
1387
 * This function changes the lock status in the database.
1388
 *
1389
 * @param string $content what is it that we want to (un)lock: forum category, forum, thread, post
1390
 * @param int    $id      the id of the content we want to (un)lock
1391
 * @param string $action  do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
1392
 *
1393
 * @return string language variable
1394
 *
1395
 * @todo move to item manager
1396
 *
1397
 * @author Patrick Cool <[email protected]>, Ghent University
1398
 *
1399
 * @version february 2006, dokeos 1.8
1400
 */
1401
function change_lock_status($content, $id, $action)
1402
{
1403
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1404
    $table_forums = Database::get_course_table(TABLE_FORUM);
1405
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1406
1407
    // Determine the relevant table.
1408
    if ('forumcategory' == $content) {
1409
        $table = $table_categories;
1410
        $id_field = 'cat_id';
1411
    } elseif ('forum' == $content) {
1412
        $table = $table_forums;
1413
        $id_field = 'forum_id';
1414
    } elseif ('thread' == $content) {
1415
        $table = $table_threads;
1416
        $id_field = 'thread_id';
1417
    } else {
1418
        return get_lang('Error');
1419
    }
1420
1421
    // Determine what we are doing => defines the value for the database and the return message.
1422
    if ('lock' == $action) {
1423
        $db_locked = 1;
1424
        $return_message = get_lang('Locked: students can no longer post new messages in this forum category, forum or thread but they can still read the messages that were already posted');
1425
    } elseif ('unlock' == $action) {
1426
        $db_locked = 0;
1427
        $return_message = get_lang('Unlocked: learners can post new messages in this forum category, forum or thread');
1428
    } else {
1429
        return get_lang('Error');
1430
    }
1431
1432
    $course_id = api_get_course_int_id();
1433
1434
    // Doing the change in the database
1435
    $sql = "UPDATE $table SET locked='".Database::escape_string($db_locked)."'
1436
            WHERE c_id = $course_id AND $id_field='".Database::escape_string($id)."'";
1437
    if (Database::query($sql)) {
1438
        return $return_message;
1439
    } else {
1440
        return get_lang('Error');
1441
    }
1442
}
1443
1444
/**
1445
 * This function moves a forum or a forum category up or down.
1446
 *
1447
 * @param what $content   is it that we want to make (in)visible: forum category, forum, thread, post
1448
 * @param do   $direction we want to move it up or down
1449
 * @param the  $id        id of the content we want to make invisible
1450
 *
1451
 * @todo consider removing the table_item_property calls here but this can
1452
 * prevent unwanted side effects when a forum does not have an entry in
1453
 * the item_property table but does have one in the forum table.
1454
 *
1455
 * @return string language variable
1456
 *
1457
 * @author Patrick Cool <[email protected]>, Ghent University
1458
 *
1459
 * @version february 2006, dokeos 1.8
1460
 */
1461
function move_up_down($content, $direction, $id)
1462
{
1463
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1464
    $table_forums = Database::get_course_table(TABLE_FORUM);
1465
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1466
    $course_id = api_get_course_int_id();
1467
    $id = (int) $id;
1468
1469
    // Determine which field holds the sort order.
1470
    if ('forumcategory' == $content) {
1471
        $table = $table_categories;
1472
        $sort_column = 'cat_order';
1473
        $id_column = 'cat_id';
1474
        $sort_column = 'cat_order';
1475
    } elseif ('forum' == $content) {
1476
        $table = $table_forums;
1477
        $sort_column = 'forum_order';
1478
        $id_column = 'forum_id';
1479
        $sort_column = 'forum_order';
1480
        // We also need the forum_category of this forum.
1481
        $sql = "SELECT forum_category FROM $table_forums
1482
                WHERE c_id = $course_id AND forum_id = ".(int) $id;
1483
        $result = Database::query($sql);
1484
        $row = Database::fetch_array($result);
1485
        $forum_category = $row['forum_category'];
1486
    } else {
1487
        return get_lang('Error');
1488
    }
1489
1490
    // Determine the need for sorting ascending or descending order.
1491
    if ('down' == $direction) {
1492
        $sort_direction = 'ASC';
1493
    } elseif ('up' == $direction) {
1494
        $sort_direction = 'DESC';
1495
    } else {
1496
        return get_lang('Error');
1497
    }
1498
1499
    // The SQL statement
1500
    if ('forumcategory' == $content) {
1501
        $sql = "SELECT *
1502
                FROM $table_categories forum_categories, $table_item_property item_properties
1503
                WHERE
1504
                    forum_categories.c_id = $course_id AND
1505
                    item_properties.c_id = $course_id AND
1506
                    forum_categories.cat_id=item_properties.ref AND
1507
                    item_properties.tool='".TOOL_FORUM_CATEGORY."'
1508
                ORDER BY forum_categories.cat_order $sort_direction";
1509
    }
1510
    if ('forum' == $content) {
1511
        $sql = "SELECT *
1512
            FROM $table
1513
            WHERE
1514
                c_id = $course_id AND
1515
                forum_category='".Database::escape_string($forum_category)."'
1516
            ORDER BY forum_order $sort_direction";
1517
    }
1518
    // Finding the items that need to be switched.
1519
    $result = Database::query($sql);
1520
    $found = false;
1521
    while ($row = Database::fetch_array($result)) {
1522
        if ($found) {
1523
            $next_id = $row[$id_column];
1524
            $next_sort = $row[$sort_column];
1525
            $found = false;
1526
        }
1527
        if ($id == $row[$id_column]) {
1528
            $this_id = $id;
1529
            $this_sort = $row[$sort_column];
1530
            $found = true;
1531
        }
1532
    }
1533
1534
    // Committing the switch.
1535
    // We do an extra check if we do not have illegal values. If your remove this if statement you will
1536
    // be able to mess with the sorting by refreshing the page over and over again.
1537
    if ('' != $this_sort && '' != $next_sort && '' != $next_id && '' != $this_id) {
1538
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($this_sort)."'
1539
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($next_id)."'";
1540
        Database::query($sql);
1541
1542
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($next_sort)."'
1543
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($this_id)."'";
1544
        Database::query($sql);
1545
    }
1546
1547
    return get_lang(ucfirst($content).'Moved');
1548
}
1549
1550
/**
1551
 * Retrieve all the information off the forum categories (or one specific) for the current course.
1552
 * The categories are sorted according to their sorting order (cat_order.
1553
 *
1554
 * @param int|string $id        default ''. When an id is passed we only find the information
1555
 *                              about that specific forum category. If no id is passed we get all the forum categories.
1556
 * @param int        $courseId  Optional. The course ID
1557
 * @param int        $sessionId Optional. The session ID
1558
 *
1559
 * @return CForumCategory[]
1560
 */
1561
function get_forum_categories($id = 0, $courseId = 0, $sessionId = 0)
1562
{
1563
    $repo = Container::getForumCategoryRepository();
1564
1565
    $course = api_get_course_entity($courseId);
1566
    $session = api_get_session_entity($sessionId);
1567
1568
    $qb = $repo->getResources(api_get_user_entity(api_get_user_id()), $course->getResourceNode(), $course, $session);
1569
1570
    return $qb->getQuery()->getResult();
1571
1572
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
0 ignored issues
show
Unused Code introduced by
$table_categories = Data...e(TABLE_FORUM_CATEGORY) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1573
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1574
1575
    // Condition for the session
1576
    $session_id = $sessionId ?: api_get_session_id();
1577
    $course_id = $courseId ?: api_get_course_int_id();
1578
1579
    $condition_session = api_get_session_condition(
1580
        $session_id,
1581
        true,
1582
        true,
1583
        'forum_categories.session_id'
1584
    );
1585
    $condition_session .= " AND forum_categories.c_id = $course_id AND item_properties.c_id = $course_id";
1586
1587
    if (empty($id)) {
1588
        $sql = "SELECT *
1589
                FROM $table_item_property item_properties
1590
                INNER JOIN $table_categories forum_categories
1591
                ON (
1592
                    forum_categories.cat_id = item_properties.ref AND
1593
                    item_properties.c_id = forum_categories.c_id
1594
                )
1595
                WHERE
1596
                    item_properties.visibility = 1 AND
1597
                    item_properties.tool = '".TOOL_FORUM_CATEGORY."'
1598
                    $condition_session
1599
                ORDER BY forum_categories.cat_order ASC";
1600
        if (api_is_allowed_to_edit()) {
1601
            $sql = "SELECT *
1602
                    FROM $table_item_property item_properties
1603
                    INNER JOIN $table_categories forum_categories
1604
                    ON (
1605
                        forum_categories.cat_id = item_properties.ref AND
1606
                        item_properties.c_id = forum_categories.c_id
1607
                    )
1608
                    WHERE
1609
                        item_properties.visibility<>2 AND
1610
                        item_properties.tool='".TOOL_FORUM_CATEGORY."'
1611
                        $condition_session
1612
                    ORDER BY forum_categories.cat_order ASC";
1613
        }
1614
    } else {
1615
        $sql = "SELECT *
1616
                FROM $table_item_property item_properties
1617
                INNER JOIN $table_categories forum_categories
1618
                ON (
1619
                    forum_categories.cat_id = item_properties.ref AND
1620
                    item_properties.c_id = forum_categories.c_id
1621
                )
1622
                WHERE
1623
                    item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
1624
                    forum_categories.cat_id = ".(int) $id."
1625
                    $condition_session
1626
                ORDER BY forum_categories.cat_order ASC";
1627
    }
1628
1629
    $result = Database::query($sql);
1630
    $forum_categories_list = [];
1631
    $extraFieldValue = new ExtraFieldValue('forum_category');
1632
    while ($row = Database::fetch_assoc($result)) {
1633
        $row['extra_fields'] = $extraFieldValue->getAllValuesByItem($row['cat_id']);
1634
1635
        if (empty($id)) {
1636
            $forum_categories_list[$row['cat_id']] = $row;
1637
        } else {
1638
            $forum_categories_list = $row;
1639
        }
1640
    }
1641
1642
    return $forum_categories_list;
1643
}
1644
1645
/**
1646
 * This function retrieves all the fora in a given forum category.
1647
 *
1648
 * @param int $cat_id   the id of the forum category
1649
 * @param int $courseId Optional. The course ID
1650
 *
1651
 * @return CForumForum[] containing all the information about the forums (regardless of their category)
1652
 *
1653
 * @author Patrick Cool <[email protected]>, Ghent University
1654
 *
1655
 * @version february 2006, dokeos 1.8
1656
 */
1657
function get_forums_in_category($cat_id, $courseId = 0)
1658
{
1659
    $repo = Container::getForumRepository();
1660
    $course = api_get_course_entity($courseId);
1661
1662
    $qb = $repo->getResourcesByCourse($course, null);
1663
    $qb->andWhere('resource.forumCategory = :catId')
1664
        ->setParameter('catId', $cat_id);
1665
1666
    return $qb->getQuery()->getResult();
1667
1668
    $table_forums = Database::get_course_table(TABLE_FORUM);
0 ignored issues
show
Unused Code introduced by
$table_forums = Database...urse_table(TABLE_FORUM) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1669
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1670
1671
    $forum_list = [];
1672
    $course_id = $courseId ?: api_get_course_int_id();
1673
    $cat_id = (int) $cat_id;
1674
1675
    $sql = "SELECT * FROM $table_forums forum
1676
            INNER JOIN $table_item_property item_properties
1677
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1678
            WHERE
1679
                forum.forum_category = '".$cat_id."' AND
1680
                item_properties.visibility = 1 AND
1681
                forum.c_id = $course_id AND
1682
                item_properties.c_id = $course_id AND
1683
                item_properties.tool = '".TOOL_FORUM."'
1684
            ORDER BY forum.forum_order ASC";
1685
    if (api_is_allowed_to_edit()) {
1686
        $sql = "SELECT * FROM $table_forums forum
1687
                INNER JOIN $table_item_property item_properties
1688
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1689
                WHERE
1690
                    forum.forum_category = '".$cat_id."' AND
1691
                    item_properties.visibility <> 2 AND
1692
                    item_properties.tool = '".TOOL_FORUM."' AND
1693
                    item_properties.c_id = $course_id AND
1694
                    forum.c_id = $course_id
1695
                ORDER BY forum_order ASC";
1696
    }
1697
    $result = Database::query($sql);
1698
    while ($row = Database::fetch_array($result)) {
1699
        $forum_list[$row['forum_id']] = $row;
1700
    }
1701
1702
    return $forum_list;
1703
}
1704
1705
/**
1706
 * Retrieve all the forums (regardless of their category) or of only one.
1707
 * The forums are sorted according to the forum_order.
1708
 * Since it does not take the forum category into account there probably
1709
 * will be two or more forums that have forum_order=1, ...
1710
 *
1711
 * @param int  $id                 forum id
1712
 * @param bool $includeGroupsForum
1713
 * @param int  $sessionId
1714
 *
1715
 * @return CForumForum[]
1716
 */
1717
function get_forums(
1718
    $id = 0,
1719
    $courseId = '',
1720
    $includeGroupsForum = true,
1721
    $sessionId = 0
1722
) {
1723
    $repo = Container::getForumRepository();
1724
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
1725
    $course = api_get_course_entity($courseId);
1726
    $session = api_get_session_entity($sessionId);
1727
1728
    $qb = $repo->getResourcesByCourse($course, $session);
1729
1730
    /*$qb->andWhere('resource.forumCategory = :catId')
1731
        ->setParameter('catId', $cat_id);
1732
    */
1733
    return $qb->getQuery()->getResult();
1734
1735
    $id = (int) $id;
0 ignored issues
show
Unused Code introduced by
$id = (int)$id is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1736
    $course_info = api_get_course_info($course_code);
1737
1738
    $table_forums = Database::get_course_table(TABLE_FORUM);
1739
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1740
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1741
1742
    // Condition for the session
1743
    $session_id = (int) $sessionId ?: api_get_session_id();
1744
    $sessionIdLink = 0 === $session_id ? '' : ' AND threads.session_id = item_properties.session_id';
1745
1746
    $condition_session = api_get_session_condition(
1747
        $session_id,
1748
        true,
1749
        false,
1750
        'item_properties.session_id'
1751
    );
1752
1753
    $course_id = $course_info['real_id'];
1754
1755
    $forum_list = [];
1756
    $includeGroupsForumSelect = '';
1757
    if (!$includeGroupsForum) {
1758
        $includeGroupsForumSelect = ' AND (forum_of_group = 0 OR forum_of_group IS NULL) ';
1759
    }
1760
1761
    $allowToEdit = api_is_allowed_to_edit();
1762
1763
    if (empty($id)) {
1764
        // Student
1765
        // Select all the forum information of all forums (that are visible to students).
1766
        $sql = "SELECT item_properties.*, forum.*
1767
                FROM $table_forums forum
1768
                INNER JOIN $table_item_property item_properties
1769
                ON (
1770
                    forum.forum_id = item_properties.ref AND
1771
                    forum.c_id = item_properties.c_id
1772
                )
1773
                WHERE
1774
                    item_properties.visibility = 1 AND
1775
                    item_properties.tool = '".TOOL_FORUM."'
1776
                    $condition_session AND
1777
                    forum.c_id = $course_id AND
1778
                    item_properties.c_id = $course_id
1779
                    $includeGroupsForumSelect
1780
                ORDER BY forum.forum_order ASC";
1781
1782
        // Select the number of threads of the forums (only the threads that are visible).
1783
        $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1784
                FROM $table_threads threads
1785
                INNER JOIN $table_item_property item_properties
1786
                ON (
1787
                    threads.thread_id = item_properties.ref AND
1788
                    threads.c_id = item_properties.c_id
1789
                    $sessionIdLink
1790
                )
1791
                WHERE
1792
                    item_properties.visibility=1 AND
1793
                    item_properties.tool='".TOOL_FORUM_THREAD."' AND
1794
                    threads.c_id = $course_id AND
1795
                    item_properties.c_id = $course_id
1796
                GROUP BY threads.forum_id";
1797
1798
        // Course Admin
1799
        if ($allowToEdit) {
1800
            // Select all the forum information of all forums (that are not deleted).
1801
            $sql = "SELECT item_properties.*, forum.*
1802
                    FROM $table_forums forum
1803
                    INNER JOIN $table_item_property item_properties
1804
                    ON (
1805
                        forum.forum_id = item_properties.ref AND
1806
                        forum.c_id = item_properties.c_id
1807
                    )
1808
                    WHERE
1809
                        item_properties.visibility <> 2 AND
1810
                        item_properties.tool = '".TOOL_FORUM."'
1811
                        $condition_session AND
1812
                        forum.c_id = $course_id AND
1813
                        item_properties.c_id = $course_id
1814
                        $includeGroupsForumSelect
1815
                    ORDER BY forum_order ASC";
1816
1817
            // Select the number of threads of the forums (only the threads that are not deleted).
1818
            $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1819
                    FROM $table_threads threads
1820
                    INNER JOIN $table_item_property item_properties
1821
                    ON (
1822
                        threads.thread_id = item_properties.ref AND
1823
                        threads.c_id = item_properties.c_id
1824
                        $sessionIdLink
1825
                    )
1826
                    WHERE
1827
                        item_properties.visibility<>2 AND
1828
                        item_properties.tool='".TOOL_FORUM_THREAD."' AND
1829
                        threads.c_id = $course_id AND
1830
                        item_properties.c_id = $course_id
1831
                    GROUP BY threads.forum_id";
1832
        }
1833
    } else {
1834
        // GETTING ONE SPECIFIC FORUM
1835
        /* We could do the splitup into student and course admin also but we want
1836
        to have as much as information about a certain forum as possible
1837
        so we do not take too much information into account. This function
1838
         (or this section of the function) is namely used to fill the forms
1839
        when editing a forum (and for the moment it is the only place where
1840
        we use this part of the function) */
1841
1842
        // Select all the forum information of the given forum (that is not deleted).
1843
        $sql = "SELECT * FROM $table_item_property item_properties
1844
                INNER JOIN $table_forums forum
1845
                ON (forum.forum_id = item_properties.ref AND forum.c_id = item_properties.c_id)
1846
                WHERE
1847
                    forum.forum_id = $id AND
1848
                    forum.c_id = $course_id AND
1849
                    item_properties.visibility != 2 AND
1850
                    item_properties.tool = '".TOOL_FORUM."'
1851
                ORDER BY forum_order ASC";
1852
1853
        // Select the number of threads of the forum.
1854
        $sql2 = "SELECT count(*) AS number_of_threads, forum_id
1855
                FROM $table_threads
1856
                WHERE
1857
                    forum_id = $id
1858
                GROUP BY forum_id";
1859
    }
1860
1861
    // Handling all the forum information.
1862
    $result = Database::query($sql);
1863
    while ($row = Database::fetch_assoc($result)) {
1864
        if (empty($id)) {
1865
            $forum_list[$row['forum_id']] = $row;
1866
        } else {
1867
            $forum_list = $row;
1868
        }
1869
    }
1870
1871
    // Handling the thread count information.
1872
    $result2 = Database::query($sql2);
1873
    while ($row2 = Database::fetch_array($result2)) {
1874
        if (empty($id)) {
1875
            $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
1876
        } else {
1877
            $forum_list['number_of_threads'] = $row2['number_of_threads'];
1878
        }
1879
    }
1880
1881
    /* Finding the last post information
1882
    (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)*/
1883
    if (empty($id)) {
1884
        if (is_array($forum_list)) {
1885
            foreach ($forum_list as $key => $value) {
1886
                $lastPost = get_last_post_information(
1887
                    $key,
1888
                    $allowToEdit,
1889
                    $course_id
1890
                );
1891
1892
                if ($lastPost) {
1893
                    $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
1894
                    $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
1895
                    $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
1896
                    $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
1897
                    $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1898
                    $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1899
                    $forum_list[$key]['last_post_title'] = $lastPost['last_post_title'];
1900
                    $forum_list[$key]['last_post_text'] = $lastPost['last_post_text'];
1901
                }
1902
            }
1903
        } else {
1904
            $forum_list = [];
1905
        }
1906
    } else {
1907
        $lastPost = get_last_post_information(
1908
            $id,
1909
            $allowToEdit,
1910
            $course_id
1911
        );
1912
        if ($lastPost) {
1913
            $forum_list['last_post_id'] = $lastPost['last_post_id'];
1914
            $forum_list['last_poster_id'] = $lastPost['last_poster_id'];
1915
            $forum_list['last_post_date'] = $lastPost['last_post_date'];
1916
            $forum_list['last_poster_name'] = $lastPost['last_poster_name'];
1917
            $forum_list['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1918
            $forum_list['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1919
            $forum_list['last_post_title'] = $lastPost['last_post_title'];
1920
            $forum_list['last_post_text'] = $lastPost['last_post_text'];
1921
        }
1922
    }
1923
1924
    return $forum_list;
1925
}
1926
1927
/**
1928
 * @param int  $course_id
1929
 * @param int  $thread_id
1930
 * @param int  $forum_id
1931
 * @param bool $show_visible
1932
 *
1933
 * @return array|bool
1934
 */
1935
function get_last_post_by_thread($course_id, $thread_id, $forum_id, $show_visible = true)
1936
{
1937
    if (empty($thread_id) || empty($forum_id) || empty($course_id)) {
1938
        return false;
1939
    }
1940
1941
    $thread_id = (int) $thread_id;
1942
    $forum_id = (int) $forum_id;
1943
    $course_id = (int) $course_id;
1944
1945
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1946
    $sql = "SELECT * FROM $table_posts
1947
            WHERE
1948
                c_id = $course_id AND
1949
                thread_id = $thread_id AND
1950
                forum_id = $forum_id";
1951
1952
    if (false == $show_visible) {
1953
        $sql .= ' AND visible = 1 ';
1954
    }
1955
1956
    $sql .= ' ORDER BY post_id DESC LIMIT 1';
1957
    $result = Database::query($sql);
1958
    if (Database::num_rows($result)) {
1959
        return Database::fetch_array($result, 'ASSOC');
1960
    } else {
1961
        return false;
1962
    }
1963
}
1964
1965
/**
1966
 * This function gets all the last post information of a certain forum.
1967
 *
1968
 * @param int    $forum_id        the id of the forum we want to know the last post information of
1969
 * @param bool   $show_invisibles
1970
 * @param string $course_id       course db name
1971
 * @param int    $sessionId       Optional. The session id
1972
 *
1973
 * @return array containing all the information about the last post
1974
 *               (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
1975
 *
1976
 * @author Patrick Cool <[email protected]>, Ghent University
1977
 *
1978
 * @version february 2006, dokeos 1.8
1979
 */
1980
function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null, $sessionId = 0)
1981
{
1982
    if (!isset($course_id)) {
1983
        $course_id = api_get_course_int_id();
1984
    } else {
1985
        $course_id = (int) $course_id;
1986
    }
1987
    $sessionId = $sessionId ? (int) $sessionId : api_get_session_id();
1988
1989
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1990
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1991
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1992
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1993
1994
    $forum_id = (int) $forum_id;
1995
    $return_array = [];
1996
1997
    // First get the threads to make sure there is no inconsistency in the
1998
    // database between forum and thread
1999
    $sql = "SELECT thread_id FROM $table_threads
2000
            WHERE
2001
                forum_id = $forum_id AND
2002
                c_id = $course_id AND
2003
                session_id = $sessionId";
2004
    $result = Database::query($sql);
2005
    if (0 == Database::num_rows($result)) {
2006
        // If there are no threads in this forum, then there are no posts
2007
        return [];
2008
    }
2009
    $threads = [];
2010
    while ($row = Database::fetch_row($result)) {
2011
        $threads[] = $row[0];
2012
    }
2013
    $threadsList = implode(',', $threads);
2014
    // Now get the posts that are linked to these threads
2015
    $sql = "SELECT
2016
                post.post_id,
2017
                post.forum_id,
2018
                post.poster_id,
2019
                post.poster_name,
2020
                post.post_date,
2021
                users.lastname,
2022
                users.firstname,
2023
                post.visible,
2024
                thread_properties.visibility AS thread_visibility,
2025
                forum_properties.visibility AS forum_visibility,
2026
                post.post_title,
2027
                post.post_text
2028
            FROM
2029
                $table_posts post,
2030
                $table_users users,
2031
                $table_item_property thread_properties,
2032
                $table_item_property forum_properties
2033
            WHERE
2034
                post.forum_id = $forum_id
2035
                AND post.thread_id IN ($threadsList)
2036
                AND post.poster_id = users.user_id
2037
                AND post.thread_id = thread_properties.ref
2038
                AND thread_properties.tool='".TOOL_FORUM_THREAD."'
2039
                AND post.forum_id=forum_properties.ref
2040
                AND forum_properties.tool='".TOOL_FORUM."'
2041
                AND post.c_id = $course_id AND
2042
                thread_properties.c_id = $course_id AND
2043
                forum_properties.c_id = $course_id
2044
            ORDER BY post.post_id DESC";
2045
    $result = Database::query($sql);
2046
2047
    if ($show_invisibles) {
2048
        $row = Database::fetch_array($result);
2049
        $return_array['last_post_id'] = $row['post_id'];
2050
        $return_array['last_poster_id'] = $row['poster_id'];
2051
        $return_array['last_post_date'] = $row['post_date'];
2052
        $return_array['last_poster_name'] = $row['poster_name'];
2053
        $return_array['last_poster_lastname'] = $row['lastname'];
2054
        $return_array['last_poster_firstname'] = $row['firstname'];
2055
        $return_array['last_post_title'] = $row['post_title'];
2056
        $return_array['last_post_text'] = $row['post_text'];
2057
2058
        return $return_array;
2059
    } else {
2060
        // We have to loop through the results to find the first one that is
2061
        // actually visible to students (forum_category, forum, thread AND post are visible).
2062
        while ($row = Database::fetch_array($result)) {
2063
            if ('1' == $row['visible'] && '1' == $row['thread_visibility'] && '1' == $row['forum_visibility']) {
2064
                $return_array['last_post_id'] = $row['post_id'];
2065
                $return_array['last_poster_id'] = $row['poster_id'];
2066
                $return_array['last_post_date'] = $row['post_date'];
2067
                $return_array['last_poster_name'] = $row['poster_name'];
2068
                $return_array['last_poster_lastname'] = $row['lastname'];
2069
                $return_array['last_poster_firstname'] = $row['firstname'];
2070
                $return_array['last_post_title'] = $row['post_title'];
2071
                $return_array['last_post_text'] = $row['post_text'];
2072
2073
                return $return_array;
2074
            }
2075
        }
2076
    }
2077
}
2078
2079
/**
2080
 * Retrieve all the threads of a given forum.
2081
 *
2082
 * @param int      $forum_id
2083
 * @param int|null $courseId  Optional If is null then it is considered the current course
2084
 * @param int|null $sessionId Optional. If is null then it is considered the current session
2085
 *
2086
 * @return CForumThread[]
2087
 */
2088
function get_threads($forum_id, $courseId = null, $sessionId = null)
2089
{
2090
    $repo = Container::getForumThreadRepository();
2091
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
2092
    $course = api_get_course_entity($courseId);
2093
    $session = api_get_session_entity($sessionId);
2094
2095
    $qb = $repo->getResourcesByCourse($course, $session);
2096
2097
    /*$qb->andWhere('resource.forumCategory = :catId')
2098
        ->setParameter('catId', $cat_id);
2099
    */
2100
    return $qb->getQuery()->getResult();
2101
2102
    $groupId = api_get_group_id();
0 ignored issues
show
Unused Code introduced by
$groupId = api_get_group_id() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2103
    $sessionId = null !== $sessionId ? (int) $sessionId : api_get_session_id();
2104
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2105
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2106
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2107
2108
    $courseId = null !== $courseId ? (int) $courseId : api_get_course_int_id();
2109
    $groupInfo = GroupManager::get_group_properties($groupId);
2110
    $groupCondition = '';
2111
2112
    if (!empty($groupInfo)) {
2113
        $groupIid = $groupInfo['iid'];
2114
        $groupCondition = " AND item_properties.to_group_id = '$groupIid' ";
2115
    }
2116
2117
    $sessionCondition = api_get_session_condition(
2118
        $sessionId,
2119
        true,
2120
        false,
2121
        'item_properties.session_id'
2122
    );
2123
2124
    // important note:  it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
2125
    // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
2126
    // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
2127
    // This is why it is added to the end of the field selection
2128
    $sql = "SELECT DISTINCT
2129
                item_properties.*,
2130
                users.firstname,
2131
                users.lastname,
2132
                users.user_id,
2133
                thread.locked as locked,
2134
                thread.*
2135
            FROM $table_threads thread
2136
            INNER JOIN $table_item_property item_properties
2137
            ON
2138
                thread.thread_id = item_properties.ref AND
2139
                item_properties.c_id = thread.c_id AND
2140
                item_properties.tool = '".TABLE_FORUM_THREAD."'
2141
                $groupCondition
2142
                $sessionCondition
2143
            LEFT JOIN $table_users users
2144
                ON thread.thread_poster_id = users.user_id
2145
            WHERE
2146
                item_properties.visibility='1' AND
2147
                thread.forum_id = ".(int) $forum_id." AND
2148
                thread.c_id = $courseId
2149
            ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
2150
2151
    if (api_is_allowed_to_edit()) {
2152
        $sql = "SELECT DISTINCT
2153
                    item_properties.*,
2154
                    users.firstname,
2155
                    users.lastname,
2156
                    users.user_id,
2157
                    thread.locked as locked,
2158
                    thread.*
2159
                FROM $table_threads thread
2160
                INNER JOIN $table_item_property item_properties
2161
                ON
2162
                    thread.thread_id = item_properties.ref AND
2163
                    item_properties.c_id = thread.c_id AND
2164
                    item_properties.tool = '".TABLE_FORUM_THREAD."'
2165
                    $groupCondition
2166
                    $sessionCondition
2167
                LEFT JOIN $table_users users
2168
                    ON thread.thread_poster_id=users.user_id
2169
                WHERE
2170
                    item_properties.visibility<>2 AND
2171
                    thread.forum_id = ".(int) $forum_id." AND
2172
                    thread.c_id = $courseId
2173
                ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
2174
    }
2175
    $result = Database::query($sql);
2176
    $list = [];
2177
    $alreadyAdded = [];
2178
    while ($row = Database::fetch_array($result, 'ASSOC')) {
2179
        if (in_array($row['thread_id'], $alreadyAdded)) {
2180
            continue;
2181
        }
2182
        $list[] = $row;
2183
        $alreadyAdded[] = $row['thread_id'];
2184
    }
2185
2186
    return $list;
2187
}
2188
2189
/**
2190
 * Get a thread by Id and course id.
2191
 *
2192
 * @param int $threadId the thread Id
2193
 * @param int $cId      the course id
2194
 *
2195
 * @return array containing all the information about the thread
2196
 */
2197
function getThreadInfo($threadId, $cId)
2198
{
2199
    $repo = Database::getManager()->getRepository('ChamiloCourseBundle:CForumThread');
2200
    /** @var CForumThread $forumThread */
2201
    $forumThread = $repo->findOneBy(['threadId' => $threadId, 'cId' => $cId]);
2202
2203
    $thread = [];
2204
    if ($forumThread) {
2205
        $thread['threadId'] = $forumThread->getThreadId();
2206
        $thread['threadTitle'] = $forumThread->getThreadTitle();
2207
        $thread['forumId'] = $forumThread->getForum() ? $forumThread->getForum()->getIid() : 0;
2208
        $thread['sessionId'] = $forumThread->getSessionId();
2209
        $thread['threadSticky'] = $forumThread->getThreadSticky();
2210
        $thread['locked'] = $forumThread->getLocked();
2211
        $thread['threadTitleQualify'] = $forumThread->getThreadTitleQualify();
2212
        $thread['threadQualifyMax'] = $forumThread->getThreadQualifyMax();
2213
        $thread['threadCloseDate'] = $forumThread->getThreadCloseDate();
2214
        $thread['threadWeight'] = $forumThread->getThreadWeight();
2215
        $thread['threadPeerQualify'] = $forumThread->isThreadPeerQualify();
2216
    }
2217
2218
    return $thread;
2219
}
2220
2221
/**
2222
 * Retrieve all posts of a given thread.
2223
 *
2224
 * @param int    $threadId       The thread ID
2225
 * @param string $orderDirection Optional. The direction for sort the posts
2226
 * @param bool   $recursive      Optional. If the list is recursive
2227
 * @param int    $postId         Optional. The post ID for recursive list
2228
 * @param int    $depth          Optional. The depth to indicate the indent
2229
 *
2230
 * @todo move to a repository
2231
 *
2232
 * @return array containing all the information about the posts of a given thread
2233
 */
2234
function getPosts(
2235
    CForumForum $forum,
2236
    $threadId,
2237
    $orderDirection = 'ASC',
2238
    $recursive = false,
2239
    $postId = null,
2240
    $depth = -1
2241
) {
2242
    $em = Database::getManager();
2243
2244
    if (api_is_allowed_to_edit(false, true)) {
2245
        $visibleCriteria = Criteria::expr()->neq('visible', 2);
2246
    } else {
2247
        $visibleCriteria = Criteria::expr()->eq('visible', 1);
2248
    }
2249
2250
    $criteria = Criteria::create();
2251
    $criteria
2252
        ->where(Criteria::expr()->eq('thread', $threadId))
2253
        ->andWhere(Criteria::expr()->eq('cId', $forum->getCId()))
2254
        ->andWhere($visibleCriteria)
2255
    ;
2256
2257
    $groupId = api_get_group_id();
2258
    $groupInfo = GroupManager::get_group_properties($groupId);
2259
    $filterModerated = true;
2260
2261
    if (empty($groupId)) {
2262
        if (api_is_allowed_to_edit()) {
2263
            $filterModerated = false;
2264
        }
2265
    } else {
2266
        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo) ||
2267
            api_is_allowed_to_edit(false, true)
2268
        ) {
2269
            $filterModerated = false;
2270
        }
2271
    }
2272
2273
    if ($recursive) {
2274
        $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
2275
    }
2276
2277
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
2278
    $qb->select('p')
2279
        ->addCriteria($criteria)
2280
        ->addOrderBy('p.postId', $orderDirection);
2281
2282
    if ($filterModerated && 1 == $forum->isModerated()) {
2283
        if (!api_is_allowed_to_edit(false, true)) {
2284
            $userId = api_get_user_id();
2285
            $qb->andWhere(
2286
                'p.status = 1 OR
2287
                    (p.status = '.CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
2288
                    (p.status = ".CForumPost::STATUS_REJECTED." AND p.posterId = $userId) OR
2289
                    (p.status IS NULL AND p.posterId = $userId)
2290
                    "
2291
            );
2292
        }
2293
    }
2294
2295
    $posts = $qb->getQuery()->getResult();
2296
    $depth++;
2297
2298
    $list = [];
2299
    /** @var CForumPost $post */
2300
    foreach ($posts as $post) {
2301
        $postInfo = [
2302
            'iid' => $post->getIid(),
2303
            'c_id' => $post->getCId(),
2304
            'post_id' => $post->getPostId(),
2305
            'post_title' => $post->getPostTitle(),
2306
            'post_text' => $post->getPostText(),
2307
            'thread_id' => $post->getThread() ? $post->getThread()->getIid() : 0,
2308
            'forum_id' => $post->getForumId(),
2309
            'poster_id' => $post->getPosterId(),
2310
            'poster_name' => $post->getPosterName(),
2311
            'post_date' => $post->getPostDate(),
2312
            'post_notification' => $post->getPostNotification(),
2313
            'post_parent_id' => $post->getPostParentId(),
2314
            'visible' => $post->getVisible(),
2315
            'status' => $post->getStatus(),
2316
            'indent_cnt' => $depth,
2317
        ];
2318
2319
        $posterId = $post->getPosterId();
2320
        if (!empty($posterId)) {
2321
            $user = api_get_user_entity($posterId);
2322
            if ($user) {
2323
                $postInfo['user_id'] = $user->getUserId();
2324
                $postInfo['username'] = $user->getUsername();
2325
                $postInfo['username_canonical'] = $user->getUsernameCanonical();
2326
                $postInfo['lastname'] = $user->getLastname();
2327
                $postInfo['firstname'] = $user->getFirstname();
2328
                $postInfo['complete_name'] = UserManager::formatUserFullName($user);
2329
            }
2330
        }
2331
2332
        $list[] = $postInfo;
2333
2334
        if (!$recursive) {
2335
            continue;
2336
        }
2337
        $list = array_merge(
2338
            $list,
2339
            getPosts(
2340
                $forum,
2341
                $threadId,
2342
                $orderDirection,
2343
                $recursive,
2344
                $post->getPostId(),
2345
                $depth
2346
            )
2347
        );
2348
    }
2349
2350
    return $list;
2351
}
2352
2353
/**
2354
 * This function retrieves forum thread users details.
2355
 *
2356
 * @param int $thread_id Thread ID
2357
 * @param   string  Course DB name (optional)
2358
 *
2359
 * @return Doctrine\DBAL\Driver\Statement|null array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2360
 *
2361
 * @author Christian Fasanando <[email protected]>,
2362
 *
2363
 * @todo     this function need to be improved
2364
 *
2365
 * @version octubre 2008, dokeos 1.8
2366
 */
2367
function get_thread_users_details($thread_id)
2368
{
2369
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2370
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2371
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2372
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2373
2374
    $course_id = api_get_course_int_id();
2375
2376
    $is_western_name_order = api_is_western_name_order();
2377
    if ($is_western_name_order) {
2378
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2379
    } else {
2380
        $orderby = 'ORDER BY user.lastname, user.firstname';
2381
    }
2382
2383
    if (api_get_session_id()) {
2384
        $session_info = api_get_session_info(api_get_session_id());
2385
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2386
        //not showing coaches
2387
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2388
                FROM $t_posts p, $t_users user, $t_session_rel_user session_rel_user_rel_course
2389
                WHERE
2390
                    p.poster_id = user.id AND
2391
                    user.id = session_rel_user_rel_course.user_id AND
2392
                    session_rel_user_rel_course.status<>'2' AND
2393
                    session_rel_user_rel_course.user_id NOT IN ($user_to_avoid) AND
2394
                    p.thread_id = ".(int) $thread_id.' AND
2395
                    session_id = '.api_get_session_id()." AND
2396
                    p.c_id = $course_id AND
2397
                    session_rel_user_rel_course.c_id = ".$course_id." $orderby ";
2398
    } else {
2399
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2400
                FROM $t_posts p, $t_users user, $t_course_user course_user
2401
                WHERE
2402
                    p.poster_id = user.id
2403
                    AND user.id = course_user.user_id
2404
                    AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH.'
2405
                    AND p.thread_id = '.(int) $thread_id."
2406
                    AND course_user.status NOT IN('1') AND
2407
                    p.c_id = $course_id AND
2408
                    course_user.c_id = ".$course_id." $orderby";
2409
    }
2410
2411
    return Database::query($sql);
2412
}
2413
2414
/**
2415
 * This function retrieves forum thread users qualify.
2416
 *
2417
 * @param int $thread_id Thread ID
2418
 * @param   string  Course DB name (optional)
2419
 *
2420
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2421
 *
2422
 * @author Jhon Hinojosa
2423
 *
2424
 * @todo     this function need to be improved
2425
 */
2426
function get_thread_users_qualify($thread_id)
2427
{
2428
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2429
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2430
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2431
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2432
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2433
2434
    $course_id = api_get_course_int_id();
2435
    $sessionId = api_get_session_id();
2436
2437
    $is_western_name_order = api_is_western_name_order();
2438
    if ($is_western_name_order) {
2439
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2440
    } else {
2441
        $orderby = 'ORDER BY user.lastname, user.firstname';
2442
    }
2443
2444
    if ($sessionId) {
2445
        $session_info = api_get_session_info($sessionId);
2446
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2447
        //not showing coaches
2448
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2449
                FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
2450
                WHERE poster_id = user.id
2451
                    AND post.poster_id = qualify.user_id
2452
                    AND user.id = scu.user_id
2453
                    AND scu.status<>'2'
2454
                    AND scu.user_id NOT IN ($user_to_avoid)
2455
                    AND qualify.thread_id = ".(int) $thread_id.'
2456
                    AND post.thread_id = '.(int) $thread_id."
2457
                    AND scu.session_id = $sessionId
2458
                    AND scu.c_id = ".$course_id." AND
2459
                    qualify.c_id = $course_id AND
2460
                    post.c_id = $course_id
2461
                $orderby ";
2462
    } else {
2463
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2464
                FROM $t_posts post,
2465
                     $t_qualify qualify,
2466
                     $t_users user,
2467
                     $t_course_user course_user
2468
                WHERE
2469
                     post.poster_id = user.id
2470
                     AND post.poster_id = qualify.user_id
2471
                     AND user.id = course_user.user_id
2472
                     AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH.'
2473
                     AND qualify.thread_id = '.(int) $thread_id.'
2474
                     AND post.thread_id = '.(int) $thread_id."
2475
                     AND course_user.status not in('1')
2476
                     AND course_user.c_id = $course_id
2477
                     AND qualify.c_id = $course_id
2478
                     AND post.c_id = $course_id
2479
                 $orderby ";
2480
    }
2481
2482
    return Database::query($sql);
2483
}
2484
2485
/**
2486
 * This function retrieves forum thread users not qualify.
2487
 *
2488
 * @param int $thread_id Thread ID
2489
 * @param   string  Course DB name (optional)
2490
 *
2491
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2492
 *
2493
 * @author   Jhon Hinojosa<[email protected]>,
2494
 *
2495
 * @version oct 2008, dokeos 1.8
2496
 */
2497
function get_thread_users_not_qualify($thread_id)
2498
{
2499
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2500
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2501
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2502
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2503
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2504
2505
    $is_western_name_order = api_is_western_name_order();
2506
    if ($is_western_name_order) {
2507
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2508
    } else {
2509
        $orderby = 'ORDER BY user.lastname, user.firstname';
2510
    }
2511
2512
    $course_id = api_get_course_int_id();
2513
2514
    $sql1 = "SELECT user_id FROM  $t_qualify
2515
             WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
2516
    $result1 = Database::query($sql1);
2517
    $cad = '';
2518
    while ($row = Database::fetch_array($result1)) {
2519
        $cad .= $row['user_id'].',';
2520
    }
2521
    if ('' == $cad) {
2522
        $cad = '0';
2523
    } else {
2524
        $cad = substr($cad, 0, strlen($cad) - 1);
2525
    }
2526
2527
    if (api_get_session_id()) {
2528
        $session_info = api_get_session_info(api_get_session_id());
2529
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2530
        //not showing coaches
2531
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2532
                FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
2533
                WHERE poster_id = user.id
2534
                    AND user.id NOT IN (".$cad.")
2535
                    AND user.id = session_rel_user_rel_course.user_id
2536
                    AND session_rel_user_rel_course.status<>'2'
2537
                    AND session_rel_user_rel_course.user_id NOT IN ($user_to_avoid)
2538
                    AND post.thread_id = ".(int) $thread_id.'
2539
                    AND session_id = '.api_get_session_id()."
2540
                    AND session_rel_user_rel_course.c_id = $course_id AND post.c_id = $course_id $orderby ";
2541
    } else {
2542
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2543
                FROM $t_posts post, $t_users user,$t_course_user course_user
2544
                WHERE post.poster_id = user.id
2545
                AND user.id NOT IN (".$cad.')
2546
                AND user.id = course_user.user_id
2547
                AND course_user.relation_type<>'.COURSE_RELATION_TYPE_RRHH.'
2548
                AND post.thread_id = '.(int) $thread_id."
2549
                AND course_user.status not in('1')
2550
                AND course_user.c_id = $course_id AND post.c_id = $course_id  $orderby";
2551
    }
2552
2553
    return Database::query($sql);
2554
}
2555
2556
/**
2557
 * This function retrieves all the information of a given forumcategory id.
2558
 *
2559
 * @param int $cat_id that indicates the forum
2560
 *
2561
 * @return array returns if there are category or bool returns if there aren't category
2562
 *
2563
 * @author Patrick Cool <[email protected]>, Ghent University
2564
 *
2565
 * @version february 2006, dokeos 1.8
2566
 */
2567
function get_forumcategory_information($cat_id)
2568
{
2569
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
2570
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2571
2572
    $course_id = api_get_course_int_id();
2573
    $sql = "SELECT *
2574
            FROM $table_categories forumcategories
2575
            INNER JOIN $table_item_property item_properties
2576
            ON (forumcategories.c_id = item_properties.c_id)
2577
            WHERE
2578
                forumcategories.c_id = $course_id AND
2579
                item_properties.c_id = $course_id AND
2580
                item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
2581
                item_properties.ref='".Database::escape_string($cat_id)."' AND
2582
                forumcategories.cat_id='".Database::escape_string($cat_id)."'";
2583
    $result = Database::query($sql);
2584
2585
    return Database::fetch_array($result);
2586
}
2587
2588
/**
2589
 * This function counts the number of forums inside a given category.
2590
 *
2591
 * @param int $cat_id the id of the forum category
2592
 *
2593
 * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
2594
 *      of visible forums, $countinvisible=1 would return the number of visible and invisible forums
2595
 *
2596
 * @return int the number of forums inside the given category
2597
 *
2598
 * @author Patrick Cool <[email protected]>, Ghent University
2599
 *
2600
 * @version february 2006, dokeos 1.8
2601
 */
2602
function count_number_of_forums_in_category($cat_id)
2603
{
2604
    $table_forums = Database::get_course_table(TABLE_FORUM);
2605
    $course_id = api_get_course_int_id();
2606
    $cat_id = (int) $cat_id;
2607
    $sql = "SELECT count(*) AS number_of_forums
2608
            FROM $table_forums
2609
            WHERE c_id = $course_id AND forum_category = $cat_id";
2610
    $result = Database::query($sql);
2611
    $row = Database::fetch_array($result);
2612
2613
    return $row['number_of_forums'];
2614
}
2615
2616
/**
2617
 * This function update a thread.
2618
 *
2619
 * @param array $values - The form Values
2620
 */
2621
function updateThread($values)
2622
{
2623
    if (!api_is_allowed_to_edit()) {
2624
        return '';
2625
    }
2626
2627
    $logInfo = [
2628
        'tool' => TOOL_FORUM,
2629
        'tool_id' => $values['forum_id'],
2630
        'tool_id_detail' => $values['thread_id'],
2631
        'action' => 'edit-thread',
2632
        'action_details' => 'thread',
2633
        'info' => $values['thread_title'],
2634
    ];
2635
    Event::registerLog($logInfo);
2636
2637
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
2638
    $courseId = api_get_course_int_id();
2639
    $courseCode = api_get_course_id();
2640
    $sessionId = api_get_session_id();
2641
2642
    // Simple update + set gradebook values to null
2643
    $params = [
2644
        'thread_title' => $values['thread_title'],
2645
        'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
2646
    ];
2647
    $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2648
    Database::update($threadTable, $params, $where);
2649
2650
    $id = $values['thread_id'];
2651
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
2652
        $courseCode,
2653
        LINK_FORUM_THREAD,
2654
        $id,
2655
        $sessionId
2656
    );
2657
2658
    $gradebookLink = null;
2659
    $em = Database::getManager();
2660
    if (!empty($linkInfo) && isset($linkInfo['id'])) {
2661
        $linkId = $linkInfo['id'];
2662
        $gradebookLink = $em->getRepository('ChamiloCoreBundle:GradebookLink')->find($linkId);
2663
    }
2664
2665
    // values 1 or 0
2666
    $check = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : false;
2667
    if ($check) {
2668
        $title = Security::remove_XSS(stripslashes($values['calification_notebook_title']));
2669
        $value = isset($values['numeric_calification']) ? (int) ($values['numeric_calification']) : 0;
2670
        $weight = isset($values['weight_calification']) ? (float) ($values['weight_calification']) : 0;
2671
        $description = '';
2672
        // Update title
2673
        $params = [
2674
            'thread_title_qualify' => $values['calification_notebook_title'],
2675
            'thread_qualify_max' => api_float_val($values['numeric_calification']),
2676
            'thread_weight' => api_float_val($values['weight_calification']),
2677
            'thread_peer_qualify' => $values['thread_peer_qualify'],
2678
        ];
2679
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2680
        Database::update($threadTable, $params, $where);
2681
2682
        if (!$linkInfo) {
2683
            GradebookUtils::add_resource_to_course_gradebook(
2684
                $values['category_id'],
2685
                $courseCode,
2686
                LINK_FORUM_THREAD,
2687
                $id,
2688
                $title,
2689
                $weight,
2690
                $value,
2691
                $description,
2692
                1,
2693
                $sessionId
2694
            );
2695
        } else {
2696
            if ($gradebookLink) {
2697
                $gradebookLink->setWeight($weight);
2698
                $em->persist($gradebookLink);
2699
                $em->flush();
2700
            }
2701
        }
2702
    } else {
2703
        $params = [
2704
            'thread_title_qualify' => '',
2705
            'thread_qualify_max' => 0,
2706
            'thread_weight' => 0,
2707
            'thread_peer_qualify' => 0,
2708
        ];
2709
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2710
        Database::update($threadTable, $params, $where);
2711
2712
        if (!empty($linkInfo)) {
2713
            if ($gradebookLink) {
2714
                $em->remove($gradebookLink);
2715
                $em->flush();
2716
            }
2717
        }
2718
    }
2719
2720
    $message = get_lang('The post has been modified').'<br />';
2721
    Display::addFlash(Display::return_message($message, 'confirmation', false));
2722
}
2723
2724
/**
2725
 * This function stores a new thread. This is done through an entry in the forum_thread table AND
2726
 * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet)).
2727
 *
2728
 * @param bool $showMessage
2729
 * @param int  $userId      Optional. The user ID
2730
 * @param int  $sessionId
2731
 *
2732
 * @return CForumThread
2733
 *
2734
 * @author Patrick Cool <[email protected]>, Ghent University
2735
 *
2736
 * @version february 2006, dokeos 1.8
2737
 */
2738
function store_thread(
2739
    CForumForum $forum,
2740
    array $values,
2741
    array $courseInfo = [],
2742
    $showMessage = true,
2743
    $userId = 0,
2744
    $sessionId = 0
2745
) {
2746
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
2747
    $userId = $userId ?: api_get_user_id();
2748
    $course_id = $courseInfo['real_id'];
2749
    $courseCode = $courseInfo['code'];
2750
    $groupId = api_get_group_id();
2751
    $groupInfo = GroupManager::get_group_properties($groupId);
2752
    $sessionId = $sessionId ?: api_get_session_id();
2753
2754
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2755
    $upload_ok = 1;
2756
    $has_attachment = false;
2757
    if (!empty($_FILES['user_upload']['name'])) {
2758
        $upload_ok = process_uploaded_file($_FILES['user_upload']);
2759
        $has_attachment = true;
2760
    }
2761
2762
    if (!$upload_ok) {
2763
        if ($showMessage) {
2764
            Display::addFlash(
2765
                Display::return_message(
2766
                    get_lang('No file was uploaded.'),
2767
                    'error',
2768
                    false
2769
                )
2770
            );
2771
        }
2772
2773
        return null;
2774
    }
2775
2776
    $post_date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
2777
    $visible = 1;
2778
    if ('1' == $forum->getApprovalDirectPost() && !api_is_allowed_to_edit(null, true)) {
2779
        $visible = 0; // The post has not been approved yet.
2780
    }
2781
    $clean_post_title = $values['post_title'];
2782
2783
    // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
2784
    $thread = new CForumThread();
2785
    $thread
2786
        ->setCId($course_id)
2787
        ->setThreadTitle($clean_post_title)
2788
        ->setForum($forum)
2789
        ->setThreadPosterId($userId)
2790
        ->setThreadPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2791
        ->setThreadDate($post_date)
2792
        ->setThreadSticky(isset($values['thread_sticky']) ? $values['thread_sticky'] : 0)
2793
        ->setThreadTitleQualify(
2794
            isset($values['calification_notebook_title']) ? $values['calification_notebook_title'] : null
2795
        )
2796
        ->setThreadQualifyMax(isset($values['numeric_calification']) ? (int) $values['numeric_calification'] : 0)
2797
        ->setThreadWeight(isset($values['weight_calification']) ? (int) $values['weight_calification'] : 0)
2798
        ->setThreadPeerQualify(isset($values['thread_peer_qualify']) ? (bool) $values['thread_peer_qualify'] : false)
2799
        ->setSessionId($sessionId)
2800
        ->setLpItemId(isset($values['lp_item_id']) ? (int) $values['lp_item_id'] : 0)
2801
    ;
2802
    $user = api_get_user_entity(api_get_user_id());
2803
    $course = api_get_course_entity($course_id);
2804
    $session = api_get_session_entity($sessionId);
2805
2806
    $repo = Container::getForumThreadRepository();
2807
    $em = $repo->getEntityManager();
2808
    $repo->addResourceToCourseWithParent(
2809
        $thread,
2810
        $forum->getResourceNode(),
2811
        ResourceLink::VISIBILITY_PUBLISHED,
2812
        $user,
2813
        $course,
2814
        $session,
2815
        null
2816
    );
2817
    $em->flush();
2818
2819
    // Add option gradebook qualify.
2820
    if (isset($values['thread_qualify_gradebook']) &&
2821
        1 == $values['thread_qualify_gradebook']
2822
    ) {
2823
        // Add function gradebook.
2824
        $resourcename = stripslashes($values['calification_notebook_title']);
2825
        GradebookUtils::add_resource_to_course_gradebook(
2826
            $values['category_id'],
2827
            $courseCode,
2828
            5,
2829
            $thread->getIid(),
2830
            $resourcename,
2831
            $values['weight_calification'],
2832
            $values['numeric_calification'],
2833
            '',
2834
            0,
2835
            $sessionId
2836
        );
2837
    }
2838
2839
    if ($thread->getIid()) {
2840
        $thread->setThreadId($thread->getIid());
2841
        $em->persist($thread);
2842
        $em->flush();
2843
2844
        /*api_item_property_update(
2845
            $courseInfo,
2846
            TOOL_FORUM_THREAD,
2847
            $thread->getIid(),
2848
            'ForumThreadAdded',
2849
            $userId,
2850
            $groupInfo,
2851
            null,
2852
            null,
2853
            null,
2854
            $sessionId
2855
        );*/
2856
2857
        // If the forum properties tell that the posts have to be approved
2858
        // we have to put the whole thread invisible,
2859
        // because otherwise the students will see the thread and not the post
2860
        // in the thread.
2861
        // We also have to change $visible because the post itself has to be
2862
        // visible in this case (otherwise the teacher would have
2863
        // to make the thread visible AND the post.
2864
        // Default behaviour
2865
        /*api_set_default_visibility(
2866
            $thread->getIid(),
2867
            TOOL_FORUM_THREAD,
2868
            $groupId,
2869
            $courseInfo,
2870
            $sessionId,
2871
            $userId
2872
        );*/
2873
2874
        if (0 == $visible) {
2875
            /*api_item_property_update(
2876
                $courseInfo,
2877
                TOOL_FORUM_THREAD,
2878
                $thread->getIid(),
2879
                'invisible',
2880
                $userId,
2881
                $groupInfo
2882
            );*/
2883
            $visible = 1;
2884
        }
2885
2886
        $logInfo = [
2887
            'tool' => TOOL_FORUM,
2888
            'tool_id' => $values['forum_id'],
2889
            'tool_id_detail' => $thread->getIid(),
2890
            'action' => 'new-thread',
2891
            'action_details' => '',
2892
            'info' => $clean_post_title,
2893
        ];
2894
        Event::registerLog($logInfo);
2895
    }
2896
2897
    // We now store the content in the table_post table.
2898
    $post = new CForumPost();
2899
    $post
2900
        ->setCId($course_id)
2901
        ->setPostTitle($clean_post_title)
2902
        ->setPostText($values['post_text'])
2903
        ->setThread($thread)
2904
        ->setForumId($values['forum_id'])
2905
        ->setPosterId($userId)
2906
        ->setPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2907
        ->setPostDate($post_date)
2908
        ->setPostNotification(isset($values['post_notification']) ? (int) $values['post_notification'] : null)
2909
        ->setPostParentId(null)
2910
        ->setVisible($visible)
2911
        ->setPostId(0)
2912
        ->setStatus(CForumPost::STATUS_VALIDATED);
2913
2914
    if ($forum->isModerated()) {
2915
        $post->setStatus(
2916
            api_is_course_admin() ? CForumPost::STATUS_VALIDATED : CForumPost::STATUS_WAITING_MODERATION
2917
        );
2918
    }
2919
2920
    $repo = Container::getForumPostRepository();
2921
    $em = $repo->getEntityManager();
2922
    $repo->addResourceToCourseWithParent(
2923
        $post,
2924
        $thread->getResourceNode(),
2925
        ResourceLink::VISIBILITY_PUBLISHED,
2926
        $user,
2927
        $course,
2928
        $session,
2929
        null
2930
    );
2931
    $em->flush();
2932
2933
    $postId = $post->getIid();
2934
    $thread->setThreadLastPost($postId);
2935
    $em->persist($thread);
2936
    $em->flush();
2937
2938
    $logInfo = [
2939
        'tool' => TOOL_FORUM,
2940
        'tool_id' => $values['forum_id'],
2941
        'tool_id_detail' => $thread->getIid(),
2942
        'action' => 'new-post',
2943
        'info' => $clean_post_title,
2944
    ];
2945
    Event::registerLog($logInfo);
2946
2947
    if ($postId) {
2948
        $post->setPostId($postId);
2949
        $em->persist($post);
2950
        $em->flush();
2951
    }
2952
2953
    // Update attached files
2954
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
2955
        foreach ($_POST['file_ids'] as $key => $id) {
2956
            editAttachedFile(
2957
                [
2958
                    'comment' => $_POST['file_comments'][$key],
2959
                    'post_id' => $postId,
2960
                ],
2961
                $id
2962
            );
2963
        }
2964
    }
2965
2966
    // Now we have to update the thread table to fill the thread_last_post
2967
    // field (so that we know when the thread has been updated for the last time).
2968
    $sql = "UPDATE $table_threads
2969
            SET thread_last_post = '".Database::escape_string($postId)."'
2970
            WHERE
2971
                c_id = $course_id AND
2972
                thread_id='".Database::escape_string($thread->getIid())."'";
2973
    $result = Database::query($sql);
2974
    $message = get_lang('The new thread has been added');
2975
2976
    // Overwrite default message.
2977
    if ($forum->isModerated() &&
2978
        !api_is_allowed_to_edit(null, true)
2979
    ) {
2980
        $message = get_lang('Your message has to be approved before people can view it.');
2981
    }
2982
2983
    // Storing the attachments if any.
2984
    if ($has_attachment) {
2985
        // Try to add an extension to the file if it hasn't one.
2986
        $new_file_name = add_ext_on_mime(
2987
            stripslashes($_FILES['user_upload']['name']),
2988
            $_FILES['user_upload']['type']
2989
        );
2990
2991
        if (!filter_extension($new_file_name)) {
2992
            if ($showMessage) {
2993
                Display::addFlash(Display::return_message(
2994
                    get_lang('File upload failed: this file extension or file type is prohibited'),
2995
                    'error'
2996
                ));
2997
            }
2998
        } else {
2999
            if ($result) {
3000
                add_forum_attachment_file(
3001
                    isset($values['file_comment']) ? $values['file_comment'] : null,
3002
                    $postId
3003
                );
3004
            }
3005
        }
3006
    } else {
3007
        $message .= '<br />';
3008
    }
3009
3010
    if ('1' == $forum->getApprovalDirectPost() &&
3011
        !api_is_allowed_to_edit(null, true)
3012
    ) {
3013
        $message .= get_lang('Your message has to be approved before people can view it.').'<br />';
3014
        $message .= get_lang('You can now return to the').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
3015
            get_lang('Forum').'</a><br />';
3016
    } else {
3017
        $message .= get_lang('You can now return to the').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
3018
            get_lang('Forum').'</a><br />';
3019
        $message .= get_lang('You can now return to the').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&thread='.$thread->getIid().'">'.
3020
            get_lang('Message').'</a>';
3021
    }
3022
    $reply_info['new_post_id'] = $postId;
3023
    $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3024
3025
    if (1 == $my_post_notification) {
3026
        set_notification('thread', $thread->getIid(), true);
3027
    }
3028
3029
    send_notification_mails(
3030
        $forum,
3031
        $thread,
3032
        $reply_info,
3033
        $courseInfo['code']
3034
    );
3035
3036
    Session::erase('formelements');
3037
    Session::erase('origin');
3038
    Session::erase('breadcrumbs');
3039
    Session::erase('addedresource');
3040
    Session::erase('addedresourceid');
3041
3042
    if ($showMessage) {
3043
        Display::addFlash(Display::return_message($message, 'success', false));
3044
    }
3045
3046
    return $thread;
3047
}
3048
3049
/**
3050
 * This function displays the form that is used to add a post. This can be a new thread or a reply.
3051
 *
3052
 * @param CForumForum  $forum
3053
 * @param CForumThread $thread
3054
 * @param string       $action  is the parameter that determines if we are
3055
 *                              2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
3056
 *                              3. replymessage: Replying to a message ($action =replymessage) => I-frame with the complete thread (if enabled)
3057
 *                              (I first thought to put and I-frame with the message only)
3058
 *                              4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread (if enabled).
3059
 *                              The message will be in the reply. (I first thought not to put an I-frame here)
3060
 * @param array        $form_values
3061
 * @param bool         $showPreview
3062
 *
3063
 * @return FormValidator
3064
 */
3065
function show_add_post_form(CForumForum $forum, CForumThread $thread, CForumPost $post = null, $action, $form_values = '', $showPreview = true)
3066
{
3067
    $_user = api_get_user_info();
3068
    $action = isset($action) ? Security::remove_XSS($action) : '';
3069
    $threadId = $thread->getIid();
3070
    $forumId = $forum->getIid();
3071
    $giveRevision = isset($_GET['give_revision']) && 1 == $_GET['give_revision'];
3072
    $postId = $post ? $post->getIid() : 0;
3073
3074
    $url = api_get_self().'?'.http_build_query(
3075
        [
3076
            'action' => $action,
3077
            'forum' => $forumId,
3078
            'thread' => $threadId,
3079
            'post' => $postId,
3080
        ]
3081
    ).'&'.api_get_cidreq();
3082
3083
    $form = new FormValidator(
3084
        'thread',
3085
        'post',
3086
        $url
3087
    );
3088
    $form->setConstants(['forum' => '5']);
3089
3090
    // Setting the form elements.
3091
    $form->addElement('hidden', 'forum_id', $forumId);
3092
    $form->addElement('hidden', 'thread_id', $threadId);
3093
    $form->addElement('hidden', 'action', $action);
3094
3095
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
3096
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
3097
        $form->addElement('text', 'poster_name', get_lang('Name'));
3098
        $form->applyFilter('poster_name', 'html_filter');
3099
    }
3100
3101
    $form->addElement('text', 'post_title', get_lang('Title'));
3102
    $form->addHtmlEditor(
3103
        'post_text',
3104
        get_lang('Text'),
3105
        true,
3106
        false,
3107
        api_is_allowed_to_edit(null, true) ? [
3108
            'ToolbarSet' => 'Forum',
3109
            'Width' => '100%',
3110
            'Height' => '300',
3111
        ] : [
3112
            'ToolbarSet' => 'ForumStudent',
3113
            'Width' => '100%',
3114
            'Height' => '300',
3115
            'UserStatus' => 'student',
3116
        ]
3117
    );
3118
    $form->addRule('post_text', get_lang('Required field'), 'required');
3119
3120
    if (in_array($action, ['replythread', 'replymessage', 'quote'])) {
3121
        $extraFields = new ExtraField('forum_post');
3122
        $extraFields->addElements(
3123
            $form,
3124
            null,
3125
            [], //exclude
3126
            false, // filter
3127
            false, // tag as select
3128
            ['ask_for_revision'], //show only fields
3129
            [], // order fields
3130
            [] // extra data);
3131
        );
3132
    }
3133
3134
    $iframe = null;
3135
    if ($showPreview) {
3136
        if ('newthread' !== $action && !empty($threadId)) {
3137
            $iframe = '<iframe style="border: 1px solid black"
3138
            src="iframe_thread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$threadId.'#'.$postId.'" width="100%"></iframe>';
3139
        }
3140
        if (!empty($iframe)) {
3141
            $form->addElement('label', get_lang('Thread'), $iframe);
3142
        }
3143
    }
3144
3145
    if (in_array($action, ['quote', 'replymessage'])) {
3146
        $form->addFile('user_upload[]', get_lang('Attachment'));
3147
        $form->addButton(
3148
            'add_attachment',
3149
            get_lang('Add attachment'),
3150
            'paperclip',
3151
            'default',
3152
            'default',
3153
            null,
3154
            ['id' => 'reply-add-attachment']
3155
        );
3156
    } else {
3157
        $form->addFile('user_upload', get_lang('Attachment'));
3158
    }
3159
3160
    if ($giveRevision) {
3161
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
3162
        $form->addHidden('give_revision', 1);
3163
        if (false === $hide) {
3164
            $extraField = new ExtraField('forum_post');
3165
            $extraField->addElements(
3166
                $form,
3167
                null,
3168
                [], //exclude
3169
                false, // filter
3170
                false, // tag as select
3171
                ['revision_language'], //show only fields
3172
                [], // order fields
3173
                [] // extra data
3174
            );
3175
        } else {
3176
            $form->addHidden('extra_revision_language', 1);
3177
        }
3178
    }
3179
3180
    // Setting the class and text of the form title and submit button.
3181
    if ('quote' === $action) {
3182
        $form->addButtonCreate(get_lang('Quote this message'), 'SubmitPost');
3183
    } elseif ('replythread' === $action) {
3184
        $form->addButtonCreate(get_lang('Reply to this thread'), 'SubmitPost');
3185
    } elseif ('replymessage' === $action) {
3186
        $form->addButtonCreate(get_lang('Reply to this message'), 'SubmitPost');
3187
    }
3188
3189
    $defaults['thread_peer_qualify'] = 0;
3190
    if (!empty($form_values)) {
3191
        $defaults['post_title'] = prepare4display($form_values['post_title']);
3192
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3193
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3194
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3195
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3196
    }
3197
3198
    // If we are quoting a message we have to retrieve the information of the post we are quoting so that
3199
    // we can add this as default to the textarea.
3200
    // We also need to put the parent_id of the post in a hidden form when
3201
    if (('quote' === $action || 'replymessage' === $action || $giveRevision) && !empty($postId)) {
3202
        // we are quoting or replying to a message (<> reply to a thread !!!)
3203
        $form->addHidden('post_parent_id', $post->getIid());
3204
        // If we are replying or are quoting then we display a default title.
3205
        $posterInfo = api_get_user_info($post->getPosterId());
3206
        $posterName = '';
3207
        if ($posterInfo) {
3208
            $posterName = $posterInfo['complete_name'];
3209
        }
3210
        $defaults['post_title'] = get_lang('Re:').api_html_entity_decode($post->getPostTitle(), ENT_QUOTES);
3211
        // When we are quoting a message then we have to put that message into the wysiwyg editor.
3212
        // Note: The style has to be hardcoded here because using class="quote" didn't work.
3213
        if ('quote' === $action) {
3214
            $defaults['post_text'] = '<div>&nbsp;</div>
3215
                <div style="margin: 5px;">
3216
                    <div style="font-size: 90%; font-style: italic;">'.
3217
                get_lang('Quoting').' '.$posterName.':</div>
3218
                        <div style="color: #006600; font-size: 90%;  font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.
3219
                prepare4display($post->getPostText()).'
3220
                        </div>
3221
                    </div>
3222
                <div>&nbsp;</div>
3223
                <div>&nbsp;</div>
3224
            ';
3225
        }
3226
        if ($giveRevision) {
3227
            $defaults['post_text'] = prepare4display($post->getPostText());
3228
        }
3229
    }
3230
3231
    $form->setDefaults(isset($defaults) ? $defaults : []);
3232
3233
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3234
    $form->addRule('post_title', get_lang('Required field'), 'required');
3235
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
3236
        $form->addRule(
3237
            'poster_name',
3238
            get_lang('Required field'),
3239
            'required'
3240
        );
3241
    }
3242
3243
    // Validation or display
3244
    if ($form->validate()) {
3245
        $check = Security::check_token('post');
3246
        if ($check) {
3247
            $values = $form->getSubmitValues();
3248
            if (isset($values['thread_qualify_gradebook']) &&
3249
                '1' == $values['thread_qualify_gradebook'] &&
3250
                empty($values['weight_calification'])
3251
            ) {
3252
                Display::addFlash(
3253
                    Display::return_message(
3254
                        get_lang('You must assign a score to this activity').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3255
                        'error',
3256
                        false
3257
                    )
3258
                );
3259
3260
                return false;
3261
            }
3262
3263
            $postId = 0;
3264
            $threadId = 0;
3265
3266
            switch ($action) {
3267
                case 'quote':
3268
                case 'replythread':
3269
                case 'replymessage':
3270
                    $postId = store_reply($forum, $thread, $values);
3271
3272
                    break;
3273
            }
3274
3275
            if ($postId) {
3276
                if (isset($values['give_revision']) && 1 == $values['give_revision']) {
3277
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3278
                    $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
3279
                    $params = [
3280
                        'item_id' => $postId,
3281
                        'extra_revision_language' => $revisionLanguage,
3282
                    ];
3283
3284
                    $extraFieldValues->saveFieldValues(
3285
                        $params,
3286
                        false,
3287
                        false,
3288
                        ['revision_language']
3289
                    );
3290
                }
3291
3292
                if (in_array($action, ['replythread', 'replymessage', 'quote'])) {
3293
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3294
                    $params = [
3295
                        'item_id' => $postId,
3296
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
3297
                    ];
3298
                    $extraFieldValues->saveFieldValues(
3299
                        $params,
3300
                        false,
3301
                        false,
3302
                        ['ask_for_revision']
3303
                    );
3304
                }
3305
            }
3306
3307
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3308
                [
3309
                    'forum' => $forumId,
3310
                    'thread' => $thread->getIid(),
3311
                ]
3312
            );
3313
3314
            Security::clear_token();
3315
            header('Location: '.$url);
3316
            exit;
3317
        }
3318
    } else {
3319
        $token = Security::get_token();
3320
        $form->addElement('hidden', 'sec_token');
3321
        $form->setConstants(['sec_token' => $token]);
3322
3323
        // Delete from $_SESSION forum attachment from other posts
3324
        // and keep only attachments for new post
3325
        clearAttachedFiles(FORUM_NEW_POST);
3326
        // Get forum attachment ajax table to add it to form
3327
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $forum->getIid());
3328
        $ajaxHtml = $attachmentAjaxTable;
3329
        $form->addElement('html', $ajaxHtml);
3330
3331
        return $form;
3332
    }
3333
}
3334
3335
function newThread(CForumForum $forum, $form_values = '', $showPreview = true)
3336
{
3337
    $_user = api_get_user_info();
3338
    $forumId = $forum->getIid();
3339
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
3340
    $giveRevision = isset($_GET['give_revision']) && 1 == $_GET['give_revision'];
3341
    $action = 'new_thread';
3342
3343
    $url = api_get_self().'?'.http_build_query(
3344
            [
3345
                'action' => $action,
3346
                'forum' => $forumId,
3347
                'post' => $my_post,
3348
            ]
3349
        ).'&'.api_get_cidreq();
3350
3351
    $form = new FormValidator(
3352
        'thread',
3353
        'post',
3354
        $url
3355
    );
3356
3357
    // Setting the form elements.
3358
    $form->addElement('hidden', 'forum_id', $forumId);
3359
    $form->addElement('hidden', 'thread_id', 0);
3360
    $form->addElement('hidden', 'action', $action);
3361
3362
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
3363
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
3364
        $form->addElement('text', 'poster_name', get_lang('Name'));
3365
        $form->applyFilter('poster_name', 'html_filter');
3366
    }
3367
3368
    $form->addElement('text', 'post_title', get_lang('Title'));
3369
    $form->addHtmlEditor(
3370
        'post_text',
3371
        get_lang('Text'),
3372
        true,
3373
        false,
3374
        api_is_allowed_to_edit(null, true) ? [
3375
            'ToolbarSet' => 'Forum',
3376
            'Width' => '100%',
3377
            'Height' => '300',
3378
        ] : [
3379
            'ToolbarSet' => 'ForumStudent',
3380
            'Width' => '100%',
3381
            'Height' => '300',
3382
            'UserStatus' => 'student',
3383
        ]
3384
    );
3385
    $form->addRule('post_text', get_lang('Required field'), 'required');
3386
3387
    $extraFields = new ExtraField('forum_post');
3388
    $extraFields->addElements(
3389
        $form,
3390
        null,
3391
        [], //exclude
3392
        false, // filter
3393
        false, // tag as select
3394
        ['ask_for_revision'], //show only fields
3395
        [], // order fields
3396
        [] // extra data);
3397
    );
3398
3399
    if (Gradebook::is_active() &&
3400
        (api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor())
3401
    ) {
3402
        $form->addElement('advanced_settings', 'advanced_params', get_lang('Advanced settings'));
3403
        $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
3404
3405
        // Thread qualify
3406
        if (Gradebook::is_active()) {
3407
            //Loading gradebook select
3408
            GradebookUtils::load_gradebook_select_in_tool($form);
3409
            $form->addElement(
3410
                'checkbox',
3411
                'thread_qualify_gradebook',
3412
                '',
3413
                get_lang('Grade this thread'),
3414
                'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
3415
            );
3416
        } else {
3417
            $form->addElement('hidden', 'thread_qualify_gradebook', false);
3418
        }
3419
3420
        $form->addElement('html', '<div id="options_field" style="display:none">');
3421
        $form->addElement('text', 'numeric_calification', get_lang('Maximum score'));
3422
        $form->applyFilter('numeric_calification', 'html_filter');
3423
        $form->addElement('text', 'calification_notebook_title', get_lang('Column header in Competences Report'));
3424
        $form->applyFilter('calification_notebook_title', 'html_filter');
3425
3426
        $form->addElement(
3427
            'text',
3428
            'weight_calification',
3429
            get_lang('Weight in Report'),
3430
            ['value' => '0.00', 'onfocus' => 'javascript: this.select();']
3431
        );
3432
        $form->applyFilter('weight_calification', 'html_filter');
3433
3434
        $group = [];
3435
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
3436
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
3437
        $form->addGroup(
3438
            $group,
3439
            '',
3440
            [
3441
                get_lang('Thread scored by peers'),
3442
                get_lang('Thread scored by peersComment'),
3443
            ]
3444
        );
3445
        $form->addElement('html', '</div>');
3446
        $form->addElement('html', '</div>');
3447
    }
3448
3449
    Skill::addSkillsToForm($form, ITEM_TYPE_FORUM_THREAD, 0);
3450
    $form->addElement('checkbox', 'thread_sticky', '', get_lang('This is a sticky message (appears always on top and has a special sticky icon)'));
3451
3452
    $form->addFile('user_upload', get_lang('Attachment'));
3453
3454
    if ($giveRevision) {
3455
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
3456
        $form->addHidden('give_revision', 1);
3457
        if (false === $hide) {
3458
            $extraField = new ExtraField('forum_post');
3459
            $extraField->addElements(
3460
                $form,
3461
                null,
3462
                [], //exclude
3463
                false, // filter
3464
                false, // tag as select
3465
                ['revision_language'], //show only fields
3466
                [], // order fields
3467
                [] // extra data
3468
            );
3469
        } else {
3470
            $form->addHidden('extra_revision_language', 1);
3471
        }
3472
    }
3473
    $form->addButtonCreate(get_lang('Create thread'), 'SubmitPost');
3474
3475
    $defaults['thread_peer_qualify'] = 0;
3476
    if (!empty($form_values)) {
3477
        $defaults['post_title'] = prepare4display($form_values['post_title']);
3478
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3479
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3480
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3481
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3482
    }
3483
3484
    $form->setDefaults(isset($defaults) ? $defaults : []);
3485
3486
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3487
    $form->addRule('post_title', get_lang('Required field'), 'required');
3488
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
3489
        $form->addRule(
3490
            'poster_name',
3491
            get_lang('Required field'),
3492
            'required'
3493
        );
3494
    }
3495
3496
    // Validation or display
3497
    if ($form->validate()) {
3498
        $check = Security::check_token('post');
3499
        if ($check) {
3500
            $values = $form->getSubmitValues();
3501
            if (isset($values['thread_qualify_gradebook']) &&
3502
                '1' == $values['thread_qualify_gradebook'] &&
3503
                empty($values['weight_calification'])
3504
            ) {
3505
                Display::addFlash(
3506
                    Display::return_message(
3507
                        get_lang('You must assign a score to this activity').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3508
                        'error',
3509
                        false
3510
                    )
3511
                );
3512
3513
                return false;
3514
            }
3515
3516
            $postId = 0;
3517
            $threadId = 0;
3518
3519
            $newThread = store_thread($forum, $values);
3520
            if ($newThread) {
3521
                Skill::saveSkills($form, ITEM_TYPE_FORUM_THREAD, $newThread->getIid());
3522
                $postId = $newThread->getThreadLastPost();
3523
3524
                if ($postId) {
3525
                    if (isset($values['give_revision']) && 1 == $values['give_revision']) {
3526
                        $extraFieldValues = new ExtraFieldValue('forum_post');
3527
                        $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
3528
3529
                        $params = [
3530
                            'item_id' => $postId,
3531
                            'extra_revision_language' => $revisionLanguage,
3532
                        ];
3533
3534
                        $extraFieldValues->saveFieldValues(
3535
                            $params,
3536
                            false,
3537
                            false,
3538
                            ['revision_language']
3539
                        );
3540
                    }
3541
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3542
                    $params = [
3543
                        'item_id' => $postId,
3544
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
3545
                    ];
3546
                    $extraFieldValues->saveFieldValues(
3547
                        $params,
3548
                        false,
3549
                        false,
3550
                        ['ask_for_revision']
3551
                    );
3552
                }
3553
            }
3554
3555
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3556
                [
3557
                    'forum' => $forumId,
3558
                    'thread' => $newThread->getIid(),
3559
                ]
3560
            );
3561
3562
            Security::clear_token();
3563
            header('Location: '.$url);
3564
            exit;
3565
        }
3566
    } else {
3567
        $token = Security::get_token();
3568
        $form->addElement('hidden', 'sec_token');
3569
        $form->setConstants(['sec_token' => $token]);
3570
3571
        // Delete from $_SESSION forum attachment from other posts
3572
        // and keep only attachments for new post
3573
        clearAttachedFiles(FORUM_NEW_POST);
3574
        // Get forum attachment ajax table to add it to form
3575
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $forum->getIid());
3576
        $ajaxHtml = $attachmentAjaxTable;
3577
        $form->addElement('html', $ajaxHtml);
3578
3579
        return $form;
3580
    }
3581
}
3582
3583
/**
3584
 * @param array $threadInfo
3585
 * @param int   $user_id
3586
 * @param int   $thread_id
3587
 * @param int   $thread_qualify
3588
 * @param int   $qualify_time
3589
 * @param int   $session_id
3590
 *
3591
 * @return array optional
3592
 *
3593
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3594
 *
3595
 * @version October 2008, dokeos  1.8.6
3596
 */
3597
function saveThreadScore(
3598
    $threadInfo,
3599
    $user_id,
3600
    $thread_id,
3601
    $thread_qualify = 0,
3602
    $qualify_time,
3603
    $session_id = 0
3604
) {
3605
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3606
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3607
3608
    $course_id = api_get_course_int_id();
3609
    $session_id = (int) $session_id;
3610
    $currentUserId = api_get_user_id();
3611
3612
    if ($user_id == (string) ((int) $user_id) &&
3613
        $thread_id == (string) ((int) $thread_id) &&
3614
        $thread_qualify == (string) ((float) $thread_qualify)
3615
    ) {
3616
        // Testing
3617
        $sql = "SELECT thread_qualify_max FROM $table_threads
3618
                WHERE c_id = $course_id AND thread_id=".$thread_id;
3619
        $res_string = Database::query($sql);
3620
        $row_string = Database::fetch_array($res_string);
3621
        if ($thread_qualify <= $row_string[0]) {
3622
            if (0 == $threadInfo['thread_peer_qualify']) {
3623
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3624
                        WHERE
3625
                            c_id = $course_id AND
3626
                            user_id = $user_id AND
3627
                            thread_id = ".$thread_id;
3628
            } else {
3629
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3630
                        WHERE
3631
                            c_id = $course_id AND
3632
                            user_id = $user_id AND
3633
                            qualify_user_id = $currentUserId AND
3634
                            thread_id = ".$thread_id;
3635
            }
3636
3637
            $result = Database::query($sql);
3638
            $row = Database::fetch_array($result);
3639
3640
            if (0 == $row[0]) {
3641
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3642
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3643
                Database::query($sql);
3644
                $insertId = Database::insert_id();
3645
                if ($insertId) {
3646
                    $sql = "UPDATE $table_threads_qualify SET id = iid
3647
                            WHERE iid = $insertId";
3648
                    Database::query($sql);
3649
                }
3650
3651
                return 'insert';
3652
            } else {
3653
                saveThreadScoreHistory(
3654
                    '1',
3655
                    $course_id,
3656
                    $user_id,
3657
                    $thread_id
3658
                );
3659
3660
                // Update
3661
                $sql = "UPDATE $table_threads_qualify
3662
                        SET
3663
                            qualify = '".$thread_qualify."',
3664
                            qualify_time = '".$qualify_time."'
3665
                        WHERE
3666
                            c_id = $course_id AND
3667
                            user_id=".$user_id.' AND
3668
                            thread_id='.$thread_id." AND
3669
                            qualify_user_id = $currentUserId
3670
                        ";
3671
                Database::query($sql);
3672
3673
                return 'update';
3674
            }
3675
        } else {
3676
            return null;
3677
        }
3678
    }
3679
}
3680
3681
/**
3682
 * This function shows qualify.
3683
 *
3684
 * @param string $option    contains the information of option to run
3685
 * @param int    $user_id   contains the information the current user id
3686
 * @param int    $thread_id contains the information the current thread id
3687
 *
3688
 * @return int qualify
3689
 *             <code> $option=1 obtained the qualification of the current thread</code>
3690
 *
3691
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3692
 *
3693
 * @version October 2008, dokeos  1.8.6
3694
 */
3695
function showQualify($option, $user_id, $thread_id)
3696
{
3697
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3698
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3699
3700
    $course_id = api_get_course_int_id();
3701
    $user_id = (int) $user_id;
3702
    $thread_id = (int) $thread_id;
3703
3704
    if (empty($user_id) || empty($thread_id)) {
3705
        return false;
3706
    }
3707
3708
    $sql = '';
3709
    switch ($option) {
3710
        case 1:
3711
            $sql = "SELECT qualify FROM $table_threads_qualify
3712
                    WHERE
3713
                        c_id = $course_id AND
3714
                        user_id=".$user_id.' AND
3715
                        thread_id='.$thread_id;
3716
3717
            break;
3718
        case 2:
3719
            $sql = "SELECT thread_qualify_max FROM $table_threads
3720
                    WHERE c_id = $course_id AND thread_id=".$thread_id;
3721
3722
            break;
3723
    }
3724
3725
    if (!empty($sql)) {
3726
        $rs = Database::query($sql);
3727
        $row = Database::fetch_array($rs);
3728
3729
        return $row[0];
3730
    }
3731
3732
    return [];
3733
}
3734
3735
/**
3736
 * This function gets qualify historical.
3737
 *
3738
 * @param int  $user_id   contains the information the current user id
3739
 * @param int  $thread_id contains the information the current thread id
3740
 * @param bool $opt       contains the information of option to run
3741
 *
3742
 * @return array
3743
 *
3744
 * @author Christian Fasanando <[email protected]>,
3745
 * @author Isaac Flores <[email protected]>,
3746
 *
3747
 * @version October 2008, dokeos  1.8.6
3748
 */
3749
function getThreadScoreHistory($user_id, $thread_id, $opt)
3750
{
3751
    $user_id = (int) $user_id;
3752
    $thread_id = (int) $thread_id;
3753
3754
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3755
    $course_id = api_get_course_int_id();
3756
3757
    if ('false' == $opt) {
3758
        $sql = "SELECT * FROM $table_threads_qualify_log
3759
                WHERE
3760
                    c_id = $course_id AND
3761
                    thread_id='".$thread_id."' AND
3762
                    user_id='".$user_id."'
3763
                ORDER BY qualify_time";
3764
    } else {
3765
        $sql = "SELECT * FROM $table_threads_qualify_log
3766
                WHERE
3767
                    c_id = $course_id AND
3768
                    thread_id='".$thread_id."' AND
3769
                    user_id='".$user_id."'
3770
                ORDER BY qualify_time DESC";
3771
    }
3772
    $rs = Database::query($sql);
3773
    $log = [];
3774
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3775
        $log[] = $row;
3776
    }
3777
3778
    return $log;
3779
}
3780
3781
/**
3782
 * This function stores qualify historical.
3783
 *
3784
 * @param bool contains the information of option to run
3785
 * @param string contains the information the current course id
3786
 * @param int contains the information the current forum id
3787
 * @param int contains the information the current user id
3788
 * @param int contains the information the current thread id
3789
 * @param int contains the information the current qualify
3790
 * @param string $option
3791
 * @param int    $course_id
3792
 * @param int    $user_id
3793
 * @param int    $thread_id
3794
 *
3795
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3796
 *
3797
 * @version October 2008, dokeos  1.8.6
3798
 */
3799
function saveThreadScoreHistory(
3800
    $option,
3801
    $course_id,
3802
    $user_id,
3803
    $thread_id
3804
) {
3805
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3806
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3807
3808
    $course_id = (int) $course_id;
3809
    $qualify_user_id = api_get_user_id();
3810
3811
    if ($user_id == (string) ((int) $user_id) &&
3812
        $thread_id == (string) ((int) $thread_id) && 1 == $option
3813
    ) {
3814
        // Extract information of thread_qualify.
3815
        $sql = "SELECT qualify, qualify_time
3816
                FROM $table_threads_qualify
3817
                WHERE
3818
                    c_id = $course_id AND
3819
                    user_id = ".$user_id.' AND
3820
                    thread_id = '.$thread_id." AND
3821
                    qualify_user_id = $qualify_user_id
3822
                ";
3823
        $rs = Database::query($sql);
3824
        $row = Database::fetch_array($rs);
3825
3826
        // Insert thread_historical.
3827
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3828
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3829
        Database::query($sql);
3830
3831
        $insertId = Database::insert_id();
3832
        if ($insertId) {
3833
            $sql = "UPDATE $table_threads_qualify_log SET id = iid
3834
                    WHERE iid = $insertId";
3835
            Database::query($sql);
3836
        }
3837
    }
3838
}
3839
3840
/**
3841
 * This function shows current thread qualify .
3842
 *
3843
 * @param int $threadId
3844
 * @param int $sessionId
3845
 * @param int $userId
3846
 *
3847
 * @return array or null if is empty
3848
 *
3849
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3850
 *
3851
 * @version December 2008, dokeos  1.8.6
3852
 */
3853
function current_qualify_of_thread($threadId, $sessionId, $userId)
3854
{
3855
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3856
3857
    $course_id = api_get_course_int_id();
3858
    $currentUserId = api_get_user_id();
3859
    $sessionId = (int) $sessionId;
3860
    $threadId = (int) $threadId;
3861
3862
    $sql = "SELECT qualify FROM $table_threads_qualify
3863
            WHERE
3864
                c_id = $course_id AND
3865
                thread_id = $threadId AND
3866
                session_id = $sessionId AND
3867
                qualify_user_id = $currentUserId AND
3868
                user_id = $userId
3869
            ";
3870
    $res = Database::query($sql);
3871
    $row = Database::fetch_array($res, 'ASSOC');
3872
3873
    return $row['qualify'];
3874
}
3875
3876
/**
3877
 * This function stores a reply in the forum_post table.
3878
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date).
3879
 *
3880
 * @param array $values
3881
 * @param int   $courseId Optional
3882
 * @param int   $userId   Optional
3883
 *
3884
 * @return int post id
3885
 */
3886
function store_reply(CForumForum $forum, CForumThread $thread, $values, $courseId = 0, $userId = 0)
3887
{
3888
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
3889
    $_course = api_get_course_info_by_id($courseId);
3890
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3891
    $post_date = api_get_utc_datetime();
3892
    $userId = $userId ?: api_get_user_id();
3893
3894
    if (1 == $forum->getAllowAnonymous()) {
3895
        if (api_is_anonymous() && empty($userId)) {
3896
            $userId = api_get_anonymous_id();
3897
        }
3898
    }
3899
3900
    if (empty($userId)) {
3901
        return false;
3902
    }
3903
3904
    $visible = 1;
3905
    if ('1' == $forum->getApprovalDirectPost() &&
3906
        !api_is_allowed_to_edit(null, true)
3907
    ) {
3908
        $visible = 0;
3909
    }
3910
3911
    $upload_ok = 1;
3912
    $new_post_id = 0;
3913
3914
    if ($upload_ok) {
3915
        $post = new CForumPost();
3916
        $post
3917
            ->setCId($courseId)
3918
            ->setPostTitle($values['post_title'])
3919
            ->setPostText(isset($values['post_text']) ?: null)
3920
            ->setThread($thread)
3921
            ->setForumId($forum->getIid())
3922
            ->setPosterId($userId)
3923
            ->setPostNotification(isset($values['post_notification']) ? $values['post_notification'] : null)
3924
            ->setPostParentId(isset($values['post_parent_id']) ? $values['post_parent_id'] : null)
3925
            ->setVisible($visible)
3926
            ->setPostDate(api_get_utc_datetime(null, false, true))
3927
        ;
3928
3929
        $repo = Container::getForumPostRepository();
3930
3931
        $user = api_get_user_entity(api_get_user_id());
3932
        $course = api_get_course_entity($courseId);
3933
        $session = api_get_session_entity();
3934
3935
        $em = $repo->getEntityManager();
3936
3937
        $repo->addResourceToCourseWithParent(
3938
            $post,
3939
            $thread->getResourceNode(),
3940
            ResourceLink::VISIBILITY_PUBLISHED,
3941
            $user,
3942
            $course,
3943
            $session,
3944
            null
3945
        );
3946
        $em->flush();
3947
3948
        $new_post_id = $post->getIid();
3949
3950
        if ($new_post_id) {
3951
            $sql = "UPDATE $table_posts SET post_id = iid WHERE iid = $new_post_id";
3952
            Database::query($sql);
3953
3954
            $values['new_post_id'] = $new_post_id;
3955
            $message = get_lang('The reply has been added');
3956
3957
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3958
                foreach ($_POST['file_ids'] as $key => $id) {
3959
                    editAttachedFile(
3960
                        [
3961
                            'comment' => $_POST['file_comments'][$key],
3962
                            'post_id' => $new_post_id,
3963
                        ],
3964
                        $id
3965
                    );
3966
                }
3967
            }
3968
3969
            // Update the thread.
3970
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
3971
3972
            // Update the forum.
3973
            /*api_item_property_update(
3974
                $_course,
3975
                TOOL_FORUM,
3976
                $values['forum_id'],
3977
                'NewMessageInForum',
3978
                $userId
3979
            );
3980
3981
            // Insert post
3982
            api_item_property_update(
3983
                $_course,
3984
                TOOL_FORUM_POST,
3985
                $new_post_id,
3986
                'NewPost',
3987
                $userId
3988
            );*/
3989
3990
            if ('1' == $forum->getApprovalDirectPost() &&
3991
                !api_is_allowed_to_edit(null, true)
3992
            ) {
3993
                $message .= '<br />'.get_lang('Your message has to be approved before people can view it.').'<br />';
3994
            }
3995
3996
            if ($forum->isModerated() &&
3997
                !api_is_allowed_to_edit(null, true)
3998
            ) {
3999
                $message .= '<br />'.get_lang('Your message has to be approved before people can view it.').'<br />';
4000
            }
4001
4002
            // Setting the notification correctly.
4003
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
4004
            if (1 == $my_post_notification) {
4005
                set_notification('thread', $values['thread_id'], true);
4006
            }
4007
4008
            send_notification_mails(
4009
                $forum,
4010
                $thread,
4011
                $values
4012
            );
4013
            add_forum_attachment_file('', $new_post_id);
4014
4015
            $logInfo = [
4016
                'tool' => TOOL_FORUM,
4017
                'tool_id' => $values['forum_id'],
4018
                'tool_id_detail' => $values['thread_id'],
4019
                'action' => 'new-post',
4020
                'action_details' => $values['action'],
4021
                'info' => $values['post_title'],
4022
            ];
4023
            Event::registerLog($logInfo);
4024
        }
4025
4026
        Session::erase('formelements');
4027
        Session::erase('origin');
4028
        Session::erase('breadcrumbs');
4029
        Session::erase('addedresource');
4030
        Session::erase('addedresourceid');
4031
4032
        Display::addFlash(Display::return_message($message, 'confirmation', false));
4033
    } else {
4034
        Display::addFlash(
4035
            Display::return_message(
4036
                get_lang('No file was uploaded.').' '.get_lang('Please select a file before pressing the upload button.'),
4037
                'error'
4038
            )
4039
        );
4040
    }
4041
4042
    return $new_post_id;
4043
}
4044
4045
/**
4046
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
4047
 *
4048
 * @param CForumPost   $post        contains all the information about the current post
4049
 * @param CForumThread $thread      contains all the information about the current thread
4050
 * @param CForumForum  $forum       contains all info about the current forum (to check if attachments are allowed)
4051
 * @param array        $form_values contains the default values to fill the form
4052
 *
4053
 * @author Patrick Cool <[email protected]>, Ghent University
4054
 *
4055
 * @version february 2006, dokeos 1.8
4056
 */
4057
function show_edit_post_form(
4058
    $post,
4059
    $thread,
4060
    $forum,
4061
    $form_values = '',
4062
    $id_attach = 0
4063
) {
4064
    // Initialize the object.
4065
    $form = new FormValidator(
4066
        'edit_post',
4067
        'post',
4068
        api_get_self().'?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&thread='.(int) ($_GET['thread']).'&post='.(int) ($_GET['post'])
4069
    );
4070
    $form->addElement('header', get_lang('Edit a post'));
4071
    // Setting the form elements.
4072
    $form->addElement('hidden', 'post_id', $post->getIid());
4073
    $form->addElement('hidden', 'thread_id', $thread->getIid());
4074
    $form->addElement('hidden', 'id_attach', $id_attach);
4075
4076
    if (empty($post->getPostParentId())) {
4077
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
4078
    }
4079
4080
    $form->addElement('text', 'post_title', get_lang('Title'));
4081
    $form->applyFilter('post_title', 'html_filter');
4082
    $form->addElement(
4083
        'html_editor',
4084
        'post_text',
4085
        get_lang('Text'),
4086
        null,
4087
        api_is_allowed_to_edit(null, true) ? [
4088
            'ToolbarSet' => 'Forum',
4089
            'Width' => '100%',
4090
            'Height' => '400',
4091
        ] : [
4092
            'ToolbarSet' => 'ForumStudent',
4093
            'Width' => '100%',
4094
            'Height' => '400',
4095
            'UserStatus' => 'student',
4096
        ]
4097
    );
4098
    $form->addRule('post_text', get_lang('Required field'), 'required');
4099
4100
    $extraFields = new ExtraField('forum_post');
4101
    $extraFields->addElements($form, $post->getIid());
4102
4103
    $form->addButtonAdvancedSettings('advanced_params');
4104
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
4105
4106
    if ($forum->isModerated() && api_is_allowed_to_edit(null, true)) {
4107
        $group = [];
4108
        $group[] = $form->createElement(
4109
            'radio',
4110
            'status',
4111
            null,
4112
            get_lang('Validated'),
4113
            1
4114
        );
4115
        $group[] = $form->createElement(
4116
            'radio',
4117
            'status',
4118
            null,
4119
            get_lang('Waiting for moderation'),
4120
            2
4121
        );
4122
        $group[] = $form->createElement(
4123
            'radio',
4124
            'status',
4125
            null,
4126
            get_lang('Rejected'),
4127
            3
4128
        );
4129
        $form->addGroup($group, 'status', get_lang('Status'));
4130
    }
4131
4132
    $defaults['status']['status'] = $post->getStatus();
4133
4134
    $form->addElement(
4135
        'checkbox',
4136
        'post_notification',
4137
        '',
4138
        get_lang('Notify me by e-mail when somebody replies')
4139
    );
4140
4141
    if (api_is_allowed_to_edit(null, true) &&
4142
        empty($post->getPostParentId())
4143
    ) {
4144
        // The sticky checkbox only appears when it is the first post of a thread.
4145
        $form->addElement(
4146
            'checkbox',
4147
            'thread_sticky',
4148
            '',
4149
            get_lang('This is a sticky message (appears always on top and has a special sticky icon)')
4150
        );
4151
        if (1 == $thread->getThreadSticky()) {
4152
            $defaults['thread_sticky'] = true;
4153
        }
4154
    }
4155
4156
    $form->addElement('html', '</div>');
4157
4158
    $form->addFile('user_upload[]', get_lang('Attachment'));
4159
    $form->addButton(
4160
        'add_attachment',
4161
        get_lang('Add attachment'),
4162
        'paperclip',
4163
        'default',
4164
        'default',
4165
        null,
4166
        ['id' => 'reply-add-attachment']
4167
    );
4168
4169
    $form->addButtonUpdate(get_lang('Edit'), 'SubmitPost');
4170
4171
    // Setting the default values for the form elements.
4172
    $defaults['post_title'] = $post->getPostTitle();
4173
    $defaults['post_text'] = $post->getPostText();
4174
4175
    if (1 == $post->getPostNotification()) {
4176
        $defaults['post_notification'] = true;
4177
    }
4178
4179
    if (!empty($form_values)) {
4180
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
4181
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
4182
    }
4183
4184
    $form->setDefaults($defaults);
4185
4186
    // The course admin can make a thread sticky (=appears with special icon and always on top).
4187
    $form->addRule('post_title', get_lang('Required field'), 'required');
4188
4189
    // Validation or display
4190
    if ($form->validate()) {
4191
        $values = $form->exportValues();
4192
        $values['item_id'] = $post->getIid();
4193
        $extraFieldValues = new ExtraFieldValue('forum_post');
4194
        $extraFieldValues->saveFieldValues($values);
4195
4196
        store_edit_post($forum, $values);
4197
    } else {
4198
        // Delete from $_SESSION forum attachment from other posts
4199
        clearAttachedFiles($post->getIid());
4200
        // Get forum attachment ajax table to add it to form
4201
        $fileData = getAttachmentsAjaxTable($post->getIid(), $forum->getIid());
4202
        $form->addElement('html', $fileData);
4203
        $form->display();
4204
    }
4205
}
4206
4207
/**
4208
 * This function stores the edit of a post in the forum_post table.
4209
 *
4210
 * @author Patrick Cool <[email protected]>, Ghent University
4211
 *
4212
 * @version february 2006, dokeos 1.8
4213
 */
4214
function store_edit_post(CForumForum $forum, $values)
4215
{
4216
    $logInfo = [
4217
        'tool' => TOOL_FORUM,
4218
        'tool_id' => $_GET['forum'],
4219
        'tool_id_detail' => $values['thread_id'],
4220
        'action' => 'edit-post',
4221
        'action_details' => 'post',
4222
        'info' => $values['post_title'],
4223
    ];
4224
    Event::registerLog($logInfo);
4225
4226
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
4227
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4228
    $course_id = api_get_course_int_id();
4229
4230
    //check if this post is the first of the thread
4231
    // First we check if the change affects the thread and if so we commit
4232
    // the changes (sticky and post_title=thread_title are relevant).
4233
4234
    $posts = getPosts($forum, $values['thread_id']);
4235
    $first_post = null;
4236
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
4237
        $first_post = $posts[0];
4238
    }
4239
4240
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
4241
        // Simple edit
4242
        $params = [
4243
            'thread_title' => $values['post_title'],
4244
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
4245
        ];
4246
        $where = ['c_id = ? AND thread_id = ?' => [$course_id, $values['thread_id']]];
4247
        Database::update($threadTable, $params, $where);
4248
    }
4249
4250
    $status = '';
4251
    $updateStatus = false;
4252
    if ($forum->isModerated()) {
4253
        if (api_is_allowed_to_edit(null, true)) {
4254
            $status = $values['status']['status'];
4255
            $updateStatus = true;
4256
        } else {
4257
            $status = CForumPost::STATUS_WAITING_MODERATION;
4258
            $updateStatus = true;
4259
        }
4260
    }
4261
4262
    // Update the post_title and the post_text.
4263
    $params = [
4264
        'post_title' => $values['post_title'],
4265
        'post_text' => $values['post_text'],
4266
        'post_notification' => isset($values['post_notification']) ? 1 : 0,
4267
    ];
4268
4269
    if ($updateStatus) {
4270
        $params['status'] = $status;
4271
    }
4272
4273
    $where = ['c_id = ? AND post_id = ?' => [$course_id, $values['post_id']]];
4274
    Database::update($table_posts, $params, $where);
4275
4276
    // Update attached files
4277
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
4278
        foreach ($_POST['file_ids'] as $key => $id) {
4279
            editAttachedFile(
4280
                [
4281
                    'comment' => $_POST['file_comments'][$key],
4282
                    'post_id' => $values['post_id'],
4283
                ],
4284
                $id
4285
            );
4286
        }
4287
    }
4288
4289
    if (!empty($values['remove_attach'])) {
4290
        delete_attachment($values['post_id']);
4291
    }
4292
4293
    if (empty($values['id_attach'])) {
4294
        add_forum_attachment_file(
4295
            isset($values['file_comment']) ? $values['file_comment'] : null,
4296
            $values['post_id']
4297
        );
4298
    } else {
4299
        edit_forum_attachment_file(
4300
            isset($values['file_comment']) ? $values['file_comment'] : null,
4301
            $values['post_id'],
4302
            $values['id_attach']
4303
        );
4304
    }
4305
4306
    $message = get_lang('The post has been modified').'<br />';
4307
    $message .= get_lang('You can now return to the').
4308
        ' <a href="viewforum.php?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&">'.get_lang('Forum').'</a><br />';
4309
    $message .= get_lang('You can now return to the').
4310
        ' <a href="viewthread.php?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&thread='.$values['thread_id'].'&post='.Security::remove_XSS($_GET['post']).'">'.get_lang('Message').'</a>';
4311
4312
    Session::erase('formelements');
4313
    Session::erase('origin');
4314
    Session::erase('breadcrumbs');
4315
    Session::erase('addedresource');
4316
    Session::erase('addedresourceid');
4317
4318
    echo Display::return_message($message, 'confirmation', false);
4319
}
4320
4321
/**
4322
 * This function displays the firstname and lastname of the user as a link to the user tool.
4323
 *
4324
 * @param string $user_id names
4325
 * @ in_title : title tootip
4326
 *
4327
 * @return string HTML
4328
 *
4329
 * @author Patrick Cool <[email protected]>, Ghent University
4330
 *
4331
 * @version february 2006, dokeos 1.8
4332
 */
4333
function display_user_link($user_id, $name, $origin = '', $in_title = '')
4334
{
4335
    if (0 != $user_id) {
4336
        $userInfo = api_get_user_info($user_id);
4337
4338
        return '<a href="'.$userInfo['profile_url'].'">'.Security::remove_XSS($userInfo['complete_name']).'</a>';
4339
    } else {
4340
        return $name.' ('.get_lang('Anonymous').')';
4341
    }
4342
}
4343
4344
/**
4345
 * This function displays the user image from the profile, with a link to the user's details.
4346
 *
4347
 * @param int    $user_id User's database ID
4348
 * @param string $name    User's name
4349
 * @param string $origin  the origin where the forum is called (example : learnpath)
4350
 *
4351
 * @return string An HTML with the anchor and the image of the user
4352
 *
4353
 * @author Julio Montoya <[email protected]>
4354
 */
4355
function display_user_image($user_id, $name, $origin = '')
4356
{
4357
    $userInfo = api_get_user_info($user_id);
4358
    $link = '<a href="'.(!empty($origin) ? '#' : $userInfo['profile_url']).'" '.(!empty($origin) ? 'target="_self"' : '').'>';
4359
4360
    if (0 != $user_id) {
4361
        return $link.'<img src="'.$userInfo['avatar'].'"  alt="'.$name.'"  title="'.$name.'" /></a>';
4362
    } else {
4363
        return $link.Display::return_icon('unknown.jpg', $name).'</a>';
4364
    }
4365
}
4366
4367
/**
4368
 * The thread view counter gets increased every time someone looks at the thread.
4369
 *
4370
 * @param int $thread_id
4371
 *
4372
 * @author Patrick Cool <[email protected]>, Ghent University
4373
 *
4374
 * @version february 2006, dokeos 1.8
4375
 */
4376
function increase_thread_view($thread_id)
4377
{
4378
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4379
    $course_id = api_get_course_int_id();
4380
4381
    $sql = "UPDATE $table_threads
4382
            SET thread_views = thread_views + 1
4383
            WHERE
4384
                c_id = $course_id AND
4385
                thread_id = '".(int) $thread_id."'";
4386
    Database::query($sql);
4387
}
4388
4389
/**
4390
 * The relies counter gets increased every time somebody replies to the thread.
4391
 *
4392
 * @author Patrick Cool <[email protected]>, Ghent University
4393
 *
4394
 * @version february 2006, dokeos 1.8
4395
 *
4396
 * @param int    $threadId
4397
 * @param string $lastPostId
4398
 * @param string $post_date
4399
 */
4400
function updateThreadInfo($threadId, $lastPostId, $post_date)
4401
{
4402
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4403
    $course_id = api_get_course_int_id();
4404
    $sql = "UPDATE $table_threads SET
4405
            thread_replies = thread_replies+1,
4406
            thread_last_post = '".Database::escape_string($lastPostId)."',
4407
            thread_date = '".Database::escape_string($post_date)."'
4408
            WHERE
4409
                c_id = $course_id AND
4410
                thread_id='".Database::escape_string($threadId)."'"; // this needs to be cleaned first
4411
    Database::query($sql);
4412
}
4413
4414
/**
4415
 * This function is used to find all the information about what's new in the forum tool.
4416
 *
4417
 * @author Patrick Cool <[email protected]>, Ghent University
4418
 *
4419
 * @version february 2006, dokeos 1.8
4420
 */
4421
function get_whats_new()
4422
{
4423
    $userId = api_get_user_id();
4424
    $course_id = api_get_course_int_id();
4425
4426
    if (empty($course_id) || empty($userId)) {
4427
        return false;
4428
    }
4429
4430
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4431
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
4432
4433
    $tool = TOOL_FORUM;
4434
    $lastForumAccess = Session::read('last_forum_access');
4435
4436
    if (!$lastForumAccess) {
4437
        $sql = "SELECT * FROM $tracking_last_tool_access
4438
                WHERE
4439
                    access_user_id = $userId AND
4440
                    c_id = $course_id AND
4441
                    access_tool = '".Database::escape_string($tool)."'";
4442
        $result = Database::query($sql);
4443
        $row = Database::fetch_array($result);
4444
        if ($row) {
4445
            Session::write('last_forum_access', $row['access_date']);
4446
            $lastForumAccess = $row['access_date'];
4447
        }
4448
    }
4449
4450
    $whatsNew = Session::read('whatsnew_post_info');
4451
4452
    if (!$whatsNew) {
4453
        if ('' != $lastForumAccess) {
4454
            $postInfo = [];
4455
            $sql = "SELECT * FROM $table_posts
4456
                    WHERE
4457
                        c_id = $course_id AND
4458
                        visible = 1 AND
4459
                        post_date > '".Database::escape_string($lastForumAccess)."'";
4460
            $result = Database::query($sql);
4461
            while ($row = Database::fetch_array($result)) {
4462
                $postInfo[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
4463
            }
4464
            Session::write('whatsnew_post_info', $postInfo);
4465
        }
4466
    }
4467
}
4468
4469
/**
4470
 * This function approves a post = change.
4471
 *
4472
 * @param int    $post_id the id of the post that will be deleted
4473
 * @param string $action  make the post visible or invisible
4474
 *
4475
 * @return string language variable
4476
 *
4477
 * @author Patrick Cool <[email protected]>, Ghent University
4478
 *
4479
 * @version february 2006, dokeos 1.8
4480
 */
4481
function approve_post($post_id, $action)
4482
{
4483
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4484
    $course_id = api_get_course_int_id();
4485
4486
    if ('invisible' == $action) {
4487
        $visibility_value = 0;
4488
    }
4489
4490
    if ('visible' == $action) {
4491
        $visibility_value = 1;
4492
        handle_mail_cue('post', $post_id);
4493
    }
4494
4495
    $sql = "UPDATE $table_posts SET
4496
            visible='".Database::escape_string($visibility_value)."'
4497
            WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
4498
    $return = Database::query($sql);
4499
4500
    if ($return) {
4501
        return 'PostThe visibility has been changed.';
4502
    }
4503
}
4504
4505
/**
4506
 * This function retrieves all the unapproved messages for a given forum
4507
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this).
4508
 *
4509
 * @param the $forum_id forum where we want to know the unapproved messages of
4510
 *
4511
 * @return array returns
4512
 *
4513
 * @author Patrick Cool <[email protected]>, Ghent University
4514
 *
4515
 * @version february 2006, dokeos 1.8
4516
 */
4517
function get_unaproved_messages($forum_id)
4518
{
4519
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4520
    $course_id = api_get_course_int_id();
4521
4522
    $return_array = [];
4523
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
4524
            WHERE
4525
                c_id = $course_id AND
4526
                forum_id='".Database::escape_string($forum_id)."' AND
4527
                visible='0' ";
4528
    $result = Database::query($sql);
4529
    while ($row = Database::fetch_array($result)) {
4530
        $return_array[] = $row['thread_id'];
4531
    }
4532
4533
    return $return_array;
4534
}
4535
4536
/**
4537
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
4538
 * was added to a given thread.
4539
 *
4540
 * @param array $forum reply information
4541
 */
4542
function send_notification_mails(CForumForum $forum, CForumThread $thread, $reply_info)
4543
{
4544
    $courseEntity = api_get_course_entity($forum->getCId());
4545
    $courseId = $courseEntity->getId();
4546
4547
    $sessionId = api_get_session_id();
4548
    $sessionEntity = api_get_session_entity($sessionId);
4549
4550
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4551
4552
    // First we need to check if
4553
    // 1. the forum category is visible
4554
    // 2. the forum is visible
4555
    // 3. the thread is visible
4556
    // 4. the reply is visible (=when there is)
4557
4558
    $current_forum_category = null;
4559
    if ($forum->getForumCategory()) {
4560
        $current_forum_category = $forum->getForumCategory();
4561
    }
4562
4563
    $send_mails = false;
4564
    if ($thread->isVisible($courseEntity, $sessionEntity) &&
4565
        $forum->isVisible($courseEntity, $sessionEntity) &&
4566
        ($current_forum_category && $forum->getForumCategory()->isVisible($courseEntity, $sessionEntity)) &&
4567
        '1' != $forum->getApprovalDirectPost()
4568
    ) {
4569
        $send_mails = true;
4570
    }
4571
4572
    // The forum category, the forum, the thread and the reply are visible to the user
4573
    if ($send_mails && !empty($forum)) {
4574
        $postId = isset($reply_info['new_post_id']) ? $reply_info['new_post_id'] : 0;
4575
        send_notifications($forum, $thread, $postId);
4576
    } else {
4577
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
4578
        if ($forum) {
4579
            $sql = "SELECT * FROM $table_notification
4580
                    WHERE
4581
                        c_id = ".$courseId." AND
4582
                        (
4583
                            forum_id = '".$forum->getIid()."' OR
4584
                            thread_id = '".$thread->getIid()."'
4585
                        ) ";
4586
            $result = Database::query($sql);
4587
            $user_id = api_get_user_id();
4588
            while ($row = Database::fetch_array($result)) {
4589
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
4590
                        VALUES (".$courseId.", '".$thread->getIid()."', '".(int) ($reply_info['new_post_id'])."', '$user_id' )";
4591
                Database::query($sql);
4592
            }
4593
        }
4594
    }
4595
}
4596
4597
/**
4598
 * This function is called whenever something is made visible because there might
4599
 * be new posts and the user might have indicated that (s)he wanted to be
4600
 * informed about the new posts by mail.
4601
 *
4602
 * @param string $content Content type (post, thread, forum, forum_category)
4603
 * @param int    $id      Item DB ID of the corresponding content type
4604
 *
4605
 * @return string language variable
4606
 *
4607
 * @author Patrick Cool <[email protected]>, Ghent University
4608
 *
4609
 * @version february 2006, dokeos 1.8
4610
 */
4611
function handle_mail_cue($content, $id)
4612
{
4613
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4614
    $table_forums = Database::get_course_table(TABLE_FORUM);
4615
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4616
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4617
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4618
4619
    $course_id = api_get_course_int_id();
4620
    $id = (int) $id;
4621
4622
    /* If the post is made visible we only have to send mails to the people
4623
     who indicated that they wanted to be informed for that thread.*/
4624
    if ('post' == $content) {
4625
        // Getting the information about the post (need the thread_id).
4626
        $post_info = get_post_information($id);
4627
        $thread_id = (int) $post_info['thread_id'];
4628
4629
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4630
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
4631
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4632
                WHERE
4633
                    posts.c_id = $course_id AND
4634
                    mailcue.c_id = $course_id AND
4635
                    posts.thread_id = $thread_id AND
4636
                    posts.post_notification = '1' AND
4637
                    mailcue.thread_id = $thread_id AND
4638
                    users.user_id = posts.poster_id AND
4639
                    users.active = 1
4640
                GROUP BY users.email";
4641
4642
        $result = Database::query($sql);
4643
        while ($row = Database::fetch_array($result)) {
4644
            $forumInfo = get_forum_information($post_info['forum_id']);
4645
            send_mail($row, $forumInfo, get_thread_information($post_info['forum_id'], $post_info['thread_id']), $post_info);
4646
        }
4647
    } elseif ('thread' == $content) {
4648
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4649
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email, posts.forum_id
4650
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4651
                WHERE
4652
                    posts.c_id = $course_id AND
4653
                    mailcue.c_id = $course_id AND
4654
                    posts.thread_id = $id AND
4655
                    posts.post_notification = '1' AND
4656
                    mailcue.thread_id = $id AND
4657
                    users.user_id = posts.poster_id AND
4658
                    users.active = 1
4659
                GROUP BY users.email";
4660
        $result = Database::query($sql);
4661
        while ($row = Database::fetch_array($result)) {
4662
            $forumInfo = get_forum_information($row['forum_id']);
4663
            send_mail($row, $forumInfo, get_thread_information($row['forum_id'], $id));
4664
        }
4665
4666
        // Deleting the relevant entries from the mailcue.
4667
        $sql = "DELETE FROM $table_mailcue
4668
                WHERE c_id = $course_id AND thread_id = $id";
4669
        Database::query($sql);
4670
    } elseif ('forum' == $content) {
4671
        $sql = "SELECT thread_id FROM $table_threads
4672
                WHERE c_id = $course_id AND forum_id = $id";
4673
        $result = Database::query($sql);
4674
        while ($row = Database::fetch_array($result)) {
4675
            handle_mail_cue('thread', $row['thread_id']);
4676
        }
4677
    } elseif ('forum_category' == $content) {
4678
        $sql = "SELECT forum_id FROM $table_forums
4679
                WHERE c_id = $course_id AND forum_category = $id";
4680
        $result = Database::query($sql);
4681
        while ($row = Database::fetch_array($result)) {
4682
            handle_mail_cue('forum', $row['forum_id']);
4683
        }
4684
    } else {
4685
        return get_lang('Error');
4686
    }
4687
}
4688
4689
/**
4690
 * This function sends the mails for the mail notification.
4691
 */
4692
function send_mail($userInfo, CForumForum $forum, CForumThread $thread, CForumPost $postInfo = null)
4693
{
4694
    if (empty($userInfo) || empty($forum) || empty($thread)) {
4695
        return false;
4696
    }
4697
4698
    $_course = api_get_course_info();
4699
    $user_id = api_get_user_id();
4700
    $forumId = $forum->getIid();
4701
    $threadId = $thread->getIid();
4702
4703
    $thread_link = api_get_path(WEB_CODE_PATH).
4704
        'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$threadId;
4705
4706
    $email_body = get_lang('Dear').' '.api_get_person_name($userInfo['firstname'], $userInfo['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4707
    $email_body .= get_lang('New Post in the forum').': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4708
4709
    $courseId = api_get_configuration_value('global_forums_course_id');
4710
    $subject = get_lang('New Post in the forum').' - '.$_course['official_code'].': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4711
4712
    $courseInfoTitle = get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4713
    if (!empty($courseId) && $_course['real_id'] == $courseId) {
4714
        $subject = get_lang('New Post in the forum').': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4715
        $courseInfoTitle = " <br />\n";
4716
    }
4717
    $email_body .= $courseInfoTitle;
4718
4719
    if (!empty($postInfo)) {
4720
        $text = cut(strip_tags($postInfo->getPostText()), 100);
4721
        if (!empty($text)) {
4722
            $email_body .= get_lang('Message').": <br />\n ";
4723
            $email_body .= $text;
4724
            $email_body .= "<br /><br />\n";
4725
        }
4726
    }
4727
4728
    $email_body .= get_lang('You stated that you wanted to be informed by e-mail whenever somebody replies on the thread')."<br />\n";
4729
4730
    if (!empty($thread_link)) {
4731
        $email_body .= get_lang('The thread can be found here').' : <br /><a href="'.$thread_link.'">'.$thread_link."</a>\n";
4732
    }
4733
4734
    if ($userInfo['user_id'] != $user_id) {
4735
        MessageManager::send_message(
4736
            $userInfo['user_id'],
4737
            $subject,
4738
            $email_body,
4739
            [],
4740
            [],
4741
            null,
4742
            null,
4743
            null,
4744
            null,
4745
            $user_id
4746
        );
4747
    }
4748
}
4749
4750
/**
4751
 * This function displays the form for moving a thread to a different (already existing) forum.
4752
 *
4753
 * @author Patrick Cool <[email protected]>, Ghent University
4754
 *
4755
 * @version february 2006, dokeos 1.8
4756
 */
4757
function move_thread_form()
4758
{
4759
    $form = new FormValidator(
4760
        'movepost',
4761
        'post',
4762
        api_get_self().'?forum='.(int) ($_GET['forum']).'&thread='.(int) ($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4763
    );
4764
    // The header for the form
4765
    $form->addElement('header', get_lang('Move Thread'));
4766
    // Invisible form: the thread_id
4767
    $form->addElement('hidden', 'thread_id', (int) ($_GET['thread']));
4768
    // the fora
4769
    $forum_categories = get_forum_categories();
4770
    $forums = get_forums();
4771
4772
    $htmlcontent = '<div class="row">
4773
        <div class="label">
4774
            <span class="form_required">*</span>'.get_lang('Move to').'
4775
        </div>
4776
        <div class="formw">';
4777
    $htmlcontent .= '<select name="forum">';
4778
    foreach ($forum_categories as $key => $category) {
4779
        $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
4780
        foreach ($forums as $key => $forum) {
4781
            if (isset($forum['forum_category'])) {
4782
                if ($forum['forum_category'] == $category['cat_id']) {
4783
                    $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
4784
                }
4785
            }
4786
        }
4787
        $htmlcontent .= '</optgroup>';
4788
    }
4789
    $htmlcontent .= '</select>';
4790
    $htmlcontent .= '   </div>
4791
                    </div>';
4792
4793
    $form->addElement('html', $htmlcontent);
4794
4795
    // The OK button
4796
    $form->addButtonSave(get_lang('Move Thread'), 'SubmitForum');
4797
4798
    // Validation or display
4799
    if ($form->validate()) {
4800
        $values = $form->exportValues();
4801
        if (isset($_POST['forum'])) {
4802
            store_move_thread($values);
4803
        }
4804
    } else {
4805
        $form->display();
4806
    }
4807
}
4808
4809
/**
4810
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4811
 *
4812
 * @author Patrick Cool <[email protected]>, Ghent University
4813
 *
4814
 * @version february 2006, dokeos 1.8
4815
 */
4816
function move_post_form()
4817
{
4818
    $form = new FormValidator(
4819
        'movepost',
4820
        'post',
4821
        api_get_self().'?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&thread='.(int) ($_GET['thread']).'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post'])
4822
    );
4823
    // The header for the form
4824
    $form->addElement('header', '', get_lang('Move post'));
4825
4826
    // Invisible form: the post_id
4827
    $form->addElement('hidden', 'post_id', (int) ($_GET['post']));
4828
4829
    // Dropdown list: Threads of this forum
4830
    $threads = get_threads($_GET['forum']);
4831
    //my_print_r($threads);
4832
    $threads_list[0] = get_lang('A new thread');
4833
    foreach ($threads as $key => $value) {
4834
        $threads_list[$value['thread_id']] = $value['thread_title'];
4835
    }
4836
    $form->addElement('select', 'thread', get_lang('Move toThread'), $threads_list);
4837
    $form->applyFilter('thread', 'html_filter');
4838
4839
    // The OK button
4840
    $form->addButtonSave(get_lang('Move post'), 'submit');
4841
4842
    // Setting the rules
4843
    $form->addRule('thread', get_lang('Required field'), 'required');
4844
4845
    // Validation or display
4846
    if ($form->validate()) {
4847
        $values = $form->exportValues();
4848
        store_move_post($values);
4849
    } else {
4850
        $form->display();
4851
    }
4852
}
4853
4854
/**
4855
 * @param array $values
4856
 *
4857
 * @return string HTML language variable
4858
 *
4859
 * @author Patrick Cool <[email protected]>, Ghent University
4860
 *
4861
 * @version february 2006, dokeos 1.8
4862
 */
4863
function store_move_post($values)
4864
{
4865
    $_course = api_get_course_info();
4866
    $course_id = api_get_course_int_id();
4867
4868
    $table_forums = Database::get_course_table(TABLE_FORUM);
4869
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4870
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4871
4872
    if ('0' == $values['thread']) {
4873
        $current_post = get_post_information($values['post_id']);
4874
4875
        // Storing a new thread.
4876
        $params = [
4877
            'c_id' => $course_id,
4878
            'thread_title' => $current_post['post_title'],
4879
            'forum_id' => $current_post['forum_id'],
4880
            'thread_poster_id' => $current_post['poster_id'],
4881
            'thread_poster_name' => $current_post['poster_name'],
4882
            'thread_last_post' => $values['post_id'],
4883
            'thread_date' => $current_post['post_date'],
4884
        ];
4885
4886
        $new_thread_id = Database::insert($table_threads, $params);
4887
4888
        api_item_property_update(
4889
            $_course,
4890
            TOOL_FORUM_THREAD,
4891
            $new_thread_id,
4892
            'visible',
4893
            $current_post['poster_id']
4894
        );
4895
4896
        // Moving the post to the newly created thread.
4897
        $sql = "UPDATE $table_posts SET thread_id='".(int) $new_thread_id."', post_parent_id = NULL
4898
                WHERE c_id = $course_id AND post_id='".(int) ($values['post_id'])."'";
4899
        Database::query($sql);
4900
4901
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
4902
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4903
                WHERE c_id = $course_id AND post_parent_id='".(int) ($values['post_id'])."'";
4904
        Database::query($sql);
4905
4906
        // Updating updating the number of threads in the forum.
4907
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
4908
                WHERE c_id = $course_id AND forum_id='".(int) ($current_post['forum_id'])."'";
4909
        Database::query($sql);
4910
4911
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
4912
        $sql = "SELECT * FROM $table_posts
4913
                WHERE c_id = $course_id AND thread_id='".(int) ($current_post['thread_id'])."'
4914
                ORDER BY post_id DESC";
4915
        $result = Database::query($sql);
4916
        $row = Database::fetch_array($result);
4917
        $sql = "UPDATE $table_threads SET
4918
                    thread_last_post='".$row['post_id']."',
4919
                    thread_replies=thread_replies-1
4920
                WHERE
4921
                    c_id = $course_id AND
4922
                    thread_id='".(int) ($current_post['thread_id'])."'";
4923
        Database::query($sql);
4924
    } else {
4925
        // Moving to the chosen thread.
4926
        $sql = 'SELECT thread_id FROM '.$table_posts."
4927
                WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
4928
        $result = Database::query($sql);
4929
        $row = Database::fetch_array($result);
4930
4931
        $original_thread_id = $row['thread_id'];
4932
4933
        $sql = 'SELECT thread_last_post FROM '.$table_threads."
4934
                WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4935
4936
        $result = Database::query($sql);
4937
        $row = Database::fetch_array($result);
4938
        $thread_is_last_post = $row['thread_last_post'];
4939
        // If is this thread, update the thread_last_post with the last one.
4940
4941
        if ($thread_is_last_post == $values['post_id']) {
4942
            $sql = 'SELECT post_id FROM '.$table_posts."
4943
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."'
4944
                    ORDER BY post_date DESC LIMIT 1";
4945
            $result = Database::query($sql);
4946
4947
            $row = Database::fetch_array($result);
4948
            $thread_new_last_post = $row['post_id'];
4949
4950
            $sql = 'UPDATE '.$table_threads." SET thread_last_post = '".$thread_new_last_post."'
4951
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4952
            Database::query($sql);
4953
        }
4954
4955
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
4956
                WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
4957
        Database::query($sql);
4958
4959
        // moving to the chosen thread
4960
        $sql = "UPDATE $table_posts SET thread_id='".(int) ($_POST['thread'])."', post_parent_id = NULL
4961
                WHERE c_id = $course_id AND post_id='".(int) ($values['post_id'])."'";
4962
        Database::query($sql);
4963
4964
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
4965
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4966
                WHERE c_id = $course_id AND post_parent_id='".(int) ($values['post_id'])."'";
4967
        Database::query($sql);
4968
4969
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
4970
                WHERE c_id = $course_id AND thread_id='".(int) ($_POST['thread'])."'";
4971
        Database::query($sql);
4972
    }
4973
4974
    return get_lang('Thread moved');
4975
}
4976
4977
/**
4978
 * @param array $values
4979
 *
4980
 * @return string HTML language variable
4981
 *
4982
 * @author Patrick Cool <[email protected]>, Ghent University
4983
 *
4984
 * @version february 2006, dokeos 1.8
4985
 */
4986
function store_move_thread($values)
4987
{
4988
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4989
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4990
4991
    $courseId = api_get_course_int_id();
4992
    $sessionId = api_get_session_id();
4993
4994
    $forumId = (int) ($_POST['forum']);
4995
    $threadId = (int) ($_POST['thread_id']);
4996
    $forumInfo = get_forums($forumId);
4997
4998
    // Change the thread table: Setting the forum_id to the new forum.
4999
    $sql = "UPDATE $table_threads SET forum_id = $forumId
5000
            WHERE c_id = $courseId AND thread_id = $threadId";
5001
    Database::query($sql);
5002
5003
    // Changing all the posts of the thread: setting the forum_id to the new forum.
5004
    $sql = "UPDATE $table_posts SET forum_id = $forumId
5005
            WHERE c_id = $courseId AND thread_id= $threadId";
5006
    Database::query($sql);
5007
    // Fix group id, if forum is moved to a different group
5008
    if (!empty($forumInfo['to_group_id'])) {
5009
        $groupId = $forumInfo['to_group_id'];
5010
        $item = api_get_item_property_info(
5011
            $courseId,
5012
            TABLE_FORUM_THREAD,
5013
            $threadId,
5014
            $sessionId,
5015
            $groupId
5016
        );
5017
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
5018
        $sessionCondition = api_get_session_condition($sessionId);
5019
5020
        if (!empty($item)) {
5021
            if ($item['to_group_id'] != $groupId) {
5022
                $sql = "UPDATE $table
5023
                    SET to_group_id = $groupId
5024
                    WHERE
5025
                      tool = '".TABLE_FORUM_THREAD."' AND
5026
                      c_id = $courseId AND
5027
                      ref = ".$item['ref']."
5028
                      $sessionCondition
5029
                ";
5030
                Database::query($sql);
5031
            }
5032
        } else {
5033
            $sql = "UPDATE $table
5034
                    SET to_group_id = $groupId
5035
                    WHERE
5036
                      tool = '".TABLE_FORUM_THREAD."' AND
5037
                      c_id = $courseId AND
5038
                      ref = ".$threadId."
5039
                      $sessionCondition
5040
            ";
5041
            Database::query($sql);
5042
        }
5043
    }
5044
5045
    return get_lang('Thread moved');
5046
}
5047
5048
/**
5049
 * Prepares a string for displaying by highlighting the search results inside, if any.
5050
 *
5051
 * @param string $input the input string
5052
 *
5053
 * @return string the same string with highlighted hits inside
5054
 *
5055
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
5056
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
5057
 */
5058
function prepare4display($input)
5059
{
5060
    static $highlightcolors = ['yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33'];
5061
    static $search;
5062
5063
    if (!isset($search)) {
5064
        if (isset($_POST['search_term'])) {
5065
            $search = $_POST['search_term']; // No html at all.
5066
        } elseif (isset($_GET['search'])) {
5067
            $search = $_GET['search'];
5068
        } else {
5069
            $search = '';
5070
        }
5071
    }
5072
5073
    if (!empty($search)) {
5074
        if (strstr($search, '+')) {
5075
            $search_terms = explode('+', $search);
5076
        } else {
5077
            $search_terms[] = trim($search);
5078
        }
5079
        $counter = 0;
5080
        foreach ($search_terms as $key => $search_term) {
5081
            $input = api_preg_replace(
5082
                '/'.preg_quote(trim($search_term), '/').'/i',
5083
                '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
5084
                $input
5085
            );
5086
            $counter++;
5087
        }
5088
    }
5089
5090
    // TODO: Security should be implemented outside this function.
5091
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles
5092
    // (see comments of Security::remove_XSS() method to learn about other levels).
5093
5094
    return Security::remove_XSS($input, STUDENT, true);
5095
}
5096
5097
/**
5098
 * Display the search form for the forum and display the search results.
5099
 *
5100
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5101
 *
5102
 * @version march 2008, dokeos 1.8.5
5103
 */
5104
function forum_search()
5105
{
5106
    $form = new FormValidator(
5107
        'forumsearch',
5108
        'post',
5109
        'forumsearch.php?'.api_get_cidreq()
5110
    );
5111
5112
    // Setting the form elements.
5113
    $form->addElement('header', '', get_lang('Search in the Forum'));
5114
    $form->addElement('text', 'search_term', get_lang('Search term'), ['autofocus']);
5115
    $form->applyFilter('search_term', 'html_filter');
5116
    $form->addElement('static', 'search_information', '', get_lang('Search in the ForumInformation'));
5117
    $form->addButtonSearch(get_lang('Search'));
5118
5119
    // Setting the rules.
5120
    $form->addRule('search_term', get_lang('Required field'), 'required');
5121
    $form->addRule('search_term', get_lang('Too short'), 'minlength', 3);
5122
5123
    // Validation or display.
5124
    if ($form->validate()) {
5125
        $values = $form->exportValues();
5126
        $form->setDefaults($values);
5127
        $form->display();
5128
        // Display the search results.
5129
        display_forum_search_results(stripslashes($values['search_term']));
5130
    } else {
5131
        $form->display();
5132
    }
5133
}
5134
5135
/**
5136
 * Display the search results.
5137
 *
5138
 * @param string
5139
 * @param string $search_term
5140
 *
5141
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5142
 *
5143
 * @version march 2008, dokeos 1.8.5
5144
 */
5145
function display_forum_search_results($search_term)
5146
{
5147
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5148
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5149
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5150
    $session_id = api_get_session_id();
5151
    $course_id = api_get_course_int_id();
5152
5153
    // Defining the search strings as an array.
5154
    if (strstr($search_term, '+')) {
5155
        $search_terms = explode('+', $search_term);
5156
    } else {
5157
        $search_terms[] = $search_term;
5158
    }
5159
5160
    // Search restriction.
5161
    foreach ($search_terms as $value) {
5162
        $search_restriction[] = "
5163
        (
5164
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR
5165
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%'
5166
        )";
5167
    }
5168
5169
    $sessionCondition = api_get_session_condition(
5170
        $session_id,
5171
        true,
5172
        false,
5173
        'item_property.session_id'
5174
    );
5175
5176
    $sql = "SELECT posts.*
5177
            FROM $table_posts posts
5178
            INNER JOIN $table_threads threads
5179
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5180
            INNER JOIN $table_item_property item_property
5181
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
5182
            WHERE
5183
                posts.c_id = $course_id AND
5184
                item_property.c_id = $course_id AND
5185
                item_property.visibility = 1
5186
                $sessionCondition AND
5187
                posts.visible = 1 AND
5188
                item_property.tool = '".TOOL_FORUM_THREAD."' AND
5189
                ".implode(' AND ', $search_restriction).'
5190
            GROUP BY posts.post_id';
5191
5192
    // Getting all the information of the forum categories.
5193
    $forum_categories_list = get_forum_categories();
5194
5195
    // Getting all the information of the forums.
5196
    $forum_list = get_forums();
5197
5198
    $result = Database::query($sql);
5199
    $search_results = [];
5200
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5201
        $forumId = $row['forum_id'];
5202
        $forumData = get_forums($forumId);
5203
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
5204
        $display_result = false;
5205
        /*
5206
          We only show it when
5207
          1. forum category is visible
5208
          2. forum is visible
5209
          3. thread is visible (to do)
5210
          4. post is visible
5211
         */
5212
        if (!api_is_allowed_to_edit(null, true)) {
5213
            if (!empty($category)) {
5214
                if ('1' == $category['visibility'] && '1' == $forumData['visibility']) {
5215
                    $display_result = true;
5216
                }
5217
            } else {
5218
                if ('1' == $forumData['visible']) {
5219
                    $display_result = true;
5220
                }
5221
            }
5222
        } else {
5223
            $display_result = true;
5224
        }
5225
5226
        if ($display_result) {
5227
            $categoryName = !empty($category) ? $category['cat_title'] : '';
5228
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
5229
                prepare4display($categoryName).'</a> &gt; ';
5230
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
5231
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
5232
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
5233
                prepare4display($row['post_title']).'</a>';
5234
            $search_results_item .= '<br />';
5235
            if (api_strlen($row['post_title']) > 200) {
5236
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
5237
            } else {
5238
                $search_results_item .= prepare4display($row['post_title']);
5239
            }
5240
            $search_results_item .= '</li>';
5241
            $search_results[] = $search_results_item;
5242
        }
5243
    }
5244
    echo '<legend>'.count($search_results).' '.get_lang('Search in the ForumResults').'</legend>';
5245
    echo '<ol>';
5246
    if ($search_results) {
5247
        echo implode($search_results);
5248
    }
5249
    echo '</ol>';
5250
}
5251
5252
/**
5253
 * Return the link to the forum search page.
5254
 *
5255
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5256
 *
5257
 * @version April 2008, dokeos 1.8.5
5258
 */
5259
function search_link()
5260
{
5261
    $return = '';
5262
    $origin = api_get_origin();
5263
    if ('learnpath' != $origin) {
5264
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
5265
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
5266
5267
        if (!empty($_GET['search'])) {
5268
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
5269
            $url = api_get_self().'?';
5270
            $url_parameter = [];
5271
            foreach ($_GET as $key => $value) {
5272
                if ('search' != $key) {
5273
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
5274
                }
5275
            }
5276
            $url .= implode('&', $url_parameter);
5277
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('Clean search results')).'</a>';
5278
        }
5279
    }
5280
5281
    return $return;
5282
}
5283
5284
/**
5285
 * This function adds an attachment file into a forum.
5286
 *
5287
 * @param string $file_comment a comment about file
5288
 * @param int    $last_id      from forum_post table
5289
 *
5290
 * @return false|null
5291
 */
5292
function add_forum_attachment_file($file_comment, $last_id)
5293
{
5294
    $_course = api_get_course_info();
5295
    $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5296
5297
    if (empty($_FILES['user_upload'])) {
5298
        return false;
5299
    }
5300
5301
    $filesData = [];
5302
5303
    if (!is_array($_FILES['user_upload']['name'])) {
5304
        $filesData[] = $_FILES['user_upload'];
5305
    } else {
5306
        $fileCount = count($_FILES['user_upload']['name']);
5307
        $fileKeys = array_keys($_FILES['user_upload']);
5308
        for ($i = 0; $i < $fileCount; $i++) {
5309
            foreach ($fileKeys as $key) {
5310
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5311
            }
5312
        }
5313
    }
5314
5315
    foreach ($filesData as $attachment) {
5316
        if (empty($attachment['name'])) {
5317
            continue;
5318
        }
5319
5320
        $upload_ok = process_uploaded_file($attachment);
5321
5322
        if (!$upload_ok) {
5323
            continue;
5324
        }
5325
5326
        $course_dir = $_course['path'].'/upload/forum';
5327
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5328
        $updir = $sys_course_path.$course_dir;
5329
5330
        // Try to add an extension to the file if it hasn't one.
5331
        $new_file_name = add_ext_on_mime(
5332
            stripslashes($attachment['name']),
5333
            $attachment['type']
5334
        );
5335
        // User's file name
5336
        $file_name = $attachment['name'];
5337
5338
        if (!filter_extension($new_file_name)) {
5339
            Display::addFlash(
5340
                Display::return_message(
5341
                    get_lang('File upload failed: this file extension or file type is prohibited'),
5342
                    'error'
5343
                )
5344
            );
5345
5346
            return;
5347
        }
5348
5349
        $new_file_name = uniqid('');
5350
        $new_path = $updir.'/'.$new_file_name;
5351
        $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5352
        $safe_file_comment = Database::escape_string($file_comment);
5353
        $safe_file_name = Database::escape_string($file_name);
5354
        $safe_new_file_name = Database::escape_string($new_file_name);
5355
        $last_id = (int) $last_id;
5356
        // Storing the attachments if any.
5357
        if (!$result) {
5358
            return;
5359
        }
5360
5361
        $last_id_file = Database::insert(
5362
            $agenda_forum_attachment,
5363
            [
5364
                'c_id' => api_get_course_int_id(),
5365
                'filename' => $safe_file_name,
5366
                'comment' => $safe_file_comment,
5367
                'path' => $safe_new_file_name,
5368
                'post_id' => $last_id,
5369
                'size' => (int) ($attachment['size']),
5370
            ]
5371
        );
5372
5373
        api_item_property_update(
5374
            $_course,
5375
            TOOL_FORUM_ATTACH,
5376
            $last_id_file,
5377
            'ForumAttachmentAdded',
5378
            api_get_user_id()
5379
        );
5380
    }
5381
}
5382
5383
/**
5384
 * This function edits an attachment file into a forum.
5385
 *
5386
 * @param string $file_comment a comment about file
5387
 * @param int    $post_id
5388
 * @param int    $id_attach    attachment file Id
5389
 */
5390
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
5391
{
5392
    $_course = api_get_course_info();
5393
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5394
    $course_id = api_get_course_int_id();
5395
5396
    $filesData = [];
5397
5398
    if (!is_array($_FILES['user_upload']['name'])) {
5399
        $filesData[] = $_FILES['user_upload'];
5400
    } else {
5401
        $fileCount = count($_FILES['user_upload']['name']);
5402
        $fileKeys = array_keys($_FILES['user_upload']);
5403
5404
        for ($i = 0; $i < $fileCount; $i++) {
5405
            foreach ($fileKeys as $key) {
5406
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5407
            }
5408
        }
5409
    }
5410
5411
    foreach ($filesData as $attachment) {
5412
        if (empty($attachment['name'])) {
5413
            continue;
5414
        }
5415
5416
        $upload_ok = process_uploaded_file($attachment);
5417
5418
        if (!$upload_ok) {
5419
            continue;
5420
        }
5421
5422
        $course_dir = $_course['path'].'/upload/forum';
5423
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5424
        $updir = $sys_course_path.$course_dir;
5425
5426
        // Try to add an extension to the file if it hasn't one.
5427
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
5428
        // User's file name
5429
        $file_name = $attachment['name'];
5430
5431
        if (!filter_extension($new_file_name)) {
5432
            Display::addFlash(
5433
                Display::return_message(
5434
                    get_lang('File upload failed: this file extension or file type is prohibited'),
5435
                    'error'
5436
                )
5437
            );
5438
        } else {
5439
            $new_file_name = uniqid('');
5440
            $new_path = $updir.'/'.$new_file_name;
5441
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5442
            $safe_file_comment = Database::escape_string($file_comment);
5443
            $safe_file_name = Database::escape_string($file_name);
5444
            $safe_new_file_name = Database::escape_string($new_file_name);
5445
            $safe_post_id = (int) $post_id;
5446
            $safe_id_attach = (int) $id_attach;
5447
            // Storing the attachments if any.
5448
            if ($result) {
5449
                $sql = "UPDATE $table_forum_attachment
5450
                        SET
5451
                            filename = '$safe_file_name',
5452
                            comment = '$safe_file_comment',
5453
                            path = '$safe_new_file_name',
5454
                            post_id = '$safe_post_id',
5455
                            size ='".$attachment['size']."'
5456
                        WHERE c_id = $course_id AND id = '$safe_id_attach'";
5457
                Database::query($sql);
5458
                api_item_property_update(
5459
                    $_course,
5460
                    TOOL_FORUM_ATTACH,
5461
                    $safe_id_attach,
5462
                    'ForumAttachmentUpdated',
5463
                    api_get_user_id()
5464
                );
5465
            }
5466
        }
5467
    }
5468
}
5469
5470
/**
5471
 * Show a list with all the attachments according to the post's id.
5472
 *
5473
 * @param int $postId
5474
 *
5475
 * @return array with the post info
5476
 *
5477
 * @author Julio Montoya
5478
 *
5479
 * @version avril 2008, dokeos 1.8.5
5480
 */
5481
function get_attachment($postId)
5482
{
5483
    $table = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5484
    $course_id = api_get_course_int_id();
5485
    $row = [];
5486
    $postId = (int) $postId;
5487
5488
    if (empty($postId)) {
5489
        return [];
5490
    }
5491
5492
    $sql = "SELECT iid, path, filename, comment
5493
            FROM $table
5494
            WHERE c_id = $course_id AND post_id = $postId";
5495
    $result = Database::query($sql);
5496
    if (0 != Database::num_rows($result)) {
5497
        $row = Database::fetch_array($result);
5498
    }
5499
5500
    return $row;
5501
}
5502
5503
/**
5504
 * @param int $postId
5505
 *
5506
 * @return array
5507
 */
5508
function getAllAttachment($postId)
5509
{
5510
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5511
    $courseId = api_get_course_int_id();
5512
    $postId = (int) $postId;
5513
5514
    if (empty($postId)) {
5515
        return [];
5516
    }
5517
5518
    $columns = ['iid', 'path', 'filename', 'comment'];
5519
    $conditions = [
5520
        'where' => [
5521
            'c_id = ? AND post_id = ?' => [$courseId, $postId],
5522
        ],
5523
    ];
5524
5525
    return Database::select(
5526
        $columns,
5527
        $forumAttachmentTable,
5528
        $conditions,
5529
        'all',
5530
        'ASSOC'
5531
    );
5532
}
5533
5534
/**
5535
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional).
5536
 *
5537
 * @param int $post_id
5538
 * @param int $id_attach
5539
 *
5540
 * @return bool
5541
 */
5542
function delete_attachment($postId, $id_attach = 0)
5543
{
5544
    $_course = api_get_course_info();
5545
5546
    $repo = Container::getForumPostRepository();
5547
    /** @var CForumPost $post */
5548
    $post = $repo->find($postId);
5549
5550
    $repoAttachment = Container::getForumAttachmentRepository();
5551
    $attachment = $repoAttachment->find($id_attach);
5552
    $post->removeAttachment($attachment);
5553
    $repo->getEntityManager()->persist($post);
5554
    $repo->getEntityManager()->flush();
5555
5556
    Display::addFlash(Display::return_message(get_lang('The attached file has been deleted'), 'confirmation'));
5557
5558
    return true;
5559
5560
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
0 ignored issues
show
Unused Code introduced by
$forum_table_attachment ...TABLE_FORUM_ATTACHMENT) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
5561
    $course_id = api_get_course_int_id();
5562
5563
    $cond = !empty($id_attach) ? ' iid = '.(int) $id_attach.'' : ' post_id = '.(int) $post_id.'';
5564
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
5565
    $res = Database::query($sql);
5566
    $row = Database::fetch_array($res);
5567
5568
    $course_dir = $_course['path'].'/upload/forum';
5569
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
5570
    $updir = $sys_course_path.$course_dir;
5571
    $my_path = isset($row['path']) ? $row['path'] : null;
5572
    $file = $updir.'/'.$my_path;
5573
    if (Security::check_abs_path($file, $updir)) {
5574
        @unlink($file);
5575
    }
5576
5577
    // Delete from forum_attachment table.
5578
    $sql = "DELETE FROM $forum_table_attachment
5579
            WHERE c_id = $course_id AND $cond ";
5580
    $result = Database::query($sql);
5581
    if (false !== $result) {
5582
        $affectedRows = Database::affected_rows($result);
5583
    } else {
5584
        $affectedRows = 0;
5585
    }
5586
5587
    // Update item_property.
5588
    api_item_property_update(
5589
        $_course,
5590
        TOOL_FORUM_ATTACH,
5591
        $id_attach,
5592
        'ForumAttachmentDelete',
5593
        api_get_user_id()
5594
    );
5595
5596
    if (!empty($result) && !empty($id_attach)) {
5597
        Display::addFlash(Display::return_message(get_lang('The attached file has been deleted'), 'confirmation'));
5598
    }
5599
5600
    return $affectedRows;
5601
}
5602
5603
/**
5604
 * This function gets all the forum information of the all the forum of the group.
5605
 *
5606
 * @param array $groupInfo the id of the group we need the fora of (see forum.forum_of_group)
5607
 *
5608
 * @return array
5609
 *
5610
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
5611
 */
5612
function get_forums_of_group($groupInfo)
5613
{
5614
    $table_forums = Database::get_course_table(TABLE_FORUM);
5615
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5616
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5617
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5618
    $course_id = api_get_course_int_id();
5619
    $groupId = (int) $groupInfo['id'];
5620
5621
    // Student
5622
    // Select all the forum information of all forums (that are visible to students).
5623
    $sql = "SELECT * FROM $table_forums forum
5624
            INNER JOIN $table_item_property item_properties
5625
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5626
            WHERE
5627
                forum.forum_of_group = $groupId AND
5628
                forum.c_id = $course_id AND
5629
                item_properties.c_id = $course_id AND
5630
                item_properties.visibility = 1 AND
5631
                item_properties.tool = '".TOOL_FORUM."'
5632
            ORDER BY forum.forum_order ASC";
5633
5634
    // Select the number of threads of the forums (only the threads that are visible).
5635
    $sql2 = "SELECT
5636
                count(thread_id) AS number_of_threads,
5637
                threads.forum_id
5638
            FROM $table_threads threads
5639
            INNER JOIN $table_item_property item_properties
5640
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5641
            WHERE
5642
                threads.c_id = $course_id AND
5643
                item_properties.c_id = $course_id AND
5644
                item_properties.visibility = 1 AND
5645
                item_properties.tool='".TOOL_FORUM_THREAD."'
5646
            GROUP BY threads.forum_id";
5647
5648
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
5649
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
5650
            FROM $table_posts posts
5651
            INNER JOIN $table_threads threads
5652
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5653
            INNER JOIN $table_item_property item_properties
5654
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5655
            WHERE
5656
                posts.visible=1 AND
5657
                posts.c_id = $course_id AND
5658
                item_properties.c_id = $course_id AND
5659
                threads.c_id = $course_id AND
5660
                item_properties.visibility = 1 AND
5661
                item_properties.tool='".TOOL_FORUM_THREAD."'
5662
            GROUP BY threads.forum_id";
5663
5664
    // Course Admin
5665
    if (api_is_allowed_to_edit()) {
5666
        // Select all the forum information of all forums (that are not deleted).
5667
        $sql = "SELECT *
5668
                FROM $table_forums forum
5669
                INNER JOIN $table_item_property item_properties
5670
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5671
                WHERE
5672
                    forum.forum_of_group = $groupId AND
5673
                    forum.c_id = $course_id AND
5674
                    item_properties.c_id = $course_id AND
5675
                    item_properties.visibility <> 2 AND
5676
                    item_properties.tool = '".TOOL_FORUM."'
5677
                ORDER BY forum_order ASC";
5678
5679
        // Select the number of threads of the forums (only the threads that are not deleted).
5680
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
5681
                 FROM $table_threads threads
5682
                 INNER JOIN $table_item_property item_properties
5683
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
5684
                 WHERE
5685
                    threads.c_id = $course_id AND
5686
                    item_properties.c_id = $course_id AND
5687
                    item_properties.visibility <> 2 AND
5688
                    item_properties.tool='".TOOL_FORUM_THREAD."'
5689
                GROUP BY threads.forum_id";
5690
        // Select the number of posts of the forum.
5691
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
5692
                FROM $table_posts
5693
                WHERE c_id = $course_id
5694
                GROUP BY forum_id";
5695
    }
5696
5697
    // Handling all the forum information.
5698
    $result = Database::query($sql);
5699
    $forum_list = [];
5700
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5701
        $forum_list[$row['forum_id']] = $row;
5702
    }
5703
5704
    // Handling the thread count information.
5705
    $result2 = Database::query($sql2);
5706
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5707
        if (is_array($forum_list)) {
5708
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5709
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5710
            }
5711
        }
5712
    }
5713
5714
    // Handling the post count information.
5715
    $result3 = Database::query($sql3);
5716
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5717
        if (is_array($forum_list)) {
5718
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5719
                // This is needed because sql3 takes also the deleted forums into account.
5720
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5721
            }
5722
        }
5723
    }
5724
5725
    // Finding the last post information
5726
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5727
    if (!empty($forum_list)) {
5728
        foreach ($forum_list as $key => $value) {
5729
            $lastPost = get_last_post_information($key, api_is_allowed_to_edit());
5730
            if ($lastPost) {
5731
                $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
5732
                $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
5733
                $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
5734
                $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
5735
                $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
5736
                $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
5737
            }
5738
        }
5739
    }
5740
5741
    return $forum_list;
5742
}
5743
5744
/**
5745
 * This function stores which users have to be notified of which forums or threads.
5746
 *
5747
 * @param string $content    does the user want to be notified about a forum or about a thread
5748
 * @param int    $id         the id of the forum or thread
5749
 * @param bool   $addOnly
5750
 * @param array  $userInfo
5751
 * @param array  $courseInfo
5752
 *
5753
 * @return string language variable
5754
 *
5755
 * @author  Patrick Cool <[email protected]>, Ghent University, Belgium
5756
 * @author  Julio Montoya
5757
 *
5758
 * @since   May 2008 v1.8.5
5759
 */
5760
function set_notification($content, $id, $addOnly = false, $userInfo = [], $courseInfo = [])
5761
{
5762
    $userInfo = empty($userInfo) ? api_get_user_info() : $userInfo;
5763
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
5764
    $id = (int) $id;
5765
5766
    if (empty($userInfo) || empty($courseInfo) || empty($id) || empty($content)) {
5767
        return false;
5768
    }
5769
5770
    // Database table definition
5771
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5772
5773
    $course_id = $courseInfo['real_id'];
5774
5775
    // Which database field do we have to store the id in?
5776
    $field = 'thread_id';
5777
    if ('forum' === $content) {
5778
        $field = 'forum_id';
5779
    }
5780
5781
    $userId = $userInfo['user_id'];
5782
5783
    // First we check if the notification is already set for this.
5784
    $sql = "SELECT * FROM $table_notification
5785
            WHERE
5786
                c_id = $course_id AND
5787
                $field = $id AND
5788
                user_id = $userId ";
5789
    $result = Database::query($sql);
5790
    $total = Database::num_rows($result);
5791
5792
    // If the user did not indicate that (s)he wanted to be notified already
5793
    // then we store the notification request (to prevent double notification requests).
5794
    if ($total <= 0) {
5795
        $sql = "INSERT INTO $table_notification (c_id, $field, user_id)
5796
                VALUES ($course_id, '$id','$userId')";
5797
        Database::query($sql);
5798
        Session::erase('forum_notification');
5799
        getNotificationsPerUser(0, true);
5800
5801
        return get_lang('You will be notified of new posts by e-mail.');
5802
    } else {
5803
        if (!$addOnly) {
5804
            $sql = "DELETE FROM $table_notification
5805
                    WHERE
5806
                        c_id = $course_id AND
5807
                        $field = $id AND
5808
                        user_id = $userId ";
5809
            Database::query($sql);
5810
            Session::erase('forum_notification');
5811
            getNotificationsPerUser(0, true);
5812
5813
            return get_lang('You will no longer be notified of new posts by email');
5814
        }
5815
    }
5816
}
5817
5818
/**
5819
 * This function retrieves all the email adresses of the users who wanted to be notified
5820
 * about a new post in a certain forum or thread.
5821
 *
5822
 * @param string $content does the user want to be notified about a forum or about a thread
5823
 * @param int    $id      the id of the forum or thread
5824
 *
5825
 * @return array returns
5826
 *
5827
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5828
 * @author Julio Montoya
5829
 *
5830
 * @version May 2008, dokeos 1.8.5
5831
 *
5832
 * @since May 2008, dokeos 1.8.5
5833
 */
5834
function get_notifications($content, $id)
5835
{
5836
    // Database table definition
5837
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5838
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5839
    $course_id = api_get_course_int_id();
5840
5841
    // Which database field contains the notification?
5842
    $field = 'thread_id';
5843
    if ('forum' === $content) {
5844
        $field = 'forum_id';
5845
    }
5846
5847
    $id = (int) $id;
5848
5849
    $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
5850
            FROM $table_users user, $table_notification notification
5851
            WHERE
5852
                notification.c_id = $course_id AND user.active = 1 AND
5853
                user.user_id = notification.user_id AND
5854
                notification.$field = $id ";
5855
5856
    $result = Database::query($sql);
5857
    $return = [];
5858
5859
    while ($row = Database::fetch_array($result)) {
5860
        $return['user'.$row['user_id']] = ['email' => $row['email'], 'user_id' => $row['user_id']];
5861
    }
5862
5863
    return $return;
5864
}
5865
5866
/**
5867
 * Get all the users who need to receive a notification of a new post (those subscribed to
5868
 * the forum or the thread).
5869
 *
5870
 * @param int $post_id the id of the post
5871
 *
5872
 * @return false|null
5873
 *
5874
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5875
 *
5876
 * @version May 2008, dokeos 1.8.5
5877
 *
5878
 * @since May 2008, dokeos 1.8.5
5879
 */
5880
function send_notifications(CForumForum $forum, CForumThread $thread, $post_id = 0)
5881
{
5882
    if (!$forum) {
5883
        return false;
5884
    }
5885
5886
    // Users who subscribed to the forum
5887
    $users_to_be_notified_by_forum = get_notifications('forum', $forum->getIid());
5888
5889
    // User who subscribed to the thread
5890
    $users_to_be_notified_by_thread = [];
5891
    if (!$thread) {
5892
        $users_to_be_notified_by_thread = get_notifications('thread', $thread->getIid());
5893
    }
5894
5895
    $postInfo = null;
5896
    if (!empty($post_id)) {
5897
        $postInfo = Container::getForumPostRepository()->find($post_id);
5898
    }
5899
5900
    // Merging the two
5901
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
5902
5903
    if (is_array($users_to_be_notified)) {
5904
        foreach ($users_to_be_notified as $value) {
5905
            $userInfo = api_get_user_info($value['user_id']);
5906
            send_mail($userInfo, $forum, $thread, $postInfo);
5907
        }
5908
    }
5909
}
5910
5911
/**
5912
 * Get all the notification subscriptions of the user
5913
 * = which forums and which threads does the user wants to be informed of when a new
5914
 * post is added to this thread.
5915
 *
5916
 * @param int  $user_id the user_id of a user (default = 0 => the current user)
5917
 * @param bool $force   force get the notification subscriptions (even if the information is already in the session
5918
 *
5919
 * @return array
5920
 *
5921
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5922
 *
5923
 * @version May 2008, dokeos 1.8.5
5924
 *
5925
 * @since May 2008, dokeos 1.8.5
5926
 */
5927
function getNotificationsPerUser($user_id = 0, $force = false, $course_id = 0)
5928
{
5929
    // Database table definition
5930
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5931
    $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
5932
    if (empty($course_id) || -1 == $course_id) {
5933
        return null;
5934
    }
5935
5936
    $user_id = empty($user_id) ? api_get_user_id() : (int) $user_id;
5937
5938
    if (!isset($_SESSION['forum_notification']) ||
5939
        $_SESSION['forum_notification']['course'] != $course_id ||
5940
        true == $force
5941
    ) {
5942
        $_SESSION['forum_notification']['course'] = $course_id;
5943
        $sql = "SELECT * FROM $table_notification
5944
                WHERE c_id = $course_id AND user_id='".$user_id."'";
5945
5946
        $result = Database::query($sql);
5947
        while ($row = Database::fetch_array($result)) {
5948
            if (null !== $row['forum_id']) {
5949
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
5950
            }
5951
            if (null !== $row['thread_id']) {
5952
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
5953
            }
5954
        }
5955
    }
5956
}
5957
5958
/**
5959
 * This function counts the number of post inside a thread.
5960
 *
5961
 * @param int $thread_id
5962
 *
5963
 * @return int the number of post inside a thread
5964
 *
5965
 * @author Jhon Hinojosa <[email protected]>,
5966
 *
5967
 * @version octubre 2008, dokeos 1.8
5968
 */
5969
function count_number_of_post_in_thread($thread_id)
5970
{
5971
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5972
    $course_id = api_get_course_int_id();
5973
    if (empty($course_id)) {
5974
        return 0;
5975
    }
5976
    $sql = "SELECT count(*) count FROM $table_posts
5977
            WHERE
5978
                c_id = $course_id AND
5979
                thread_id='".(int) $thread_id."' ";
5980
    $result = Database::query($sql);
5981
5982
    $count = 0;
5983
    if (Database::num_rows($result) > 0) {
5984
        $row = Database::fetch_array($result);
5985
        $count = $row['count'];
5986
    }
5987
5988
    return $count;
5989
}
5990
5991
/**
5992
 * This function counts the number of post inside a thread user.
5993
 *
5994
 * @param int $thread_id
5995
 * @param int $user_id
5996
 *
5997
 * @return int the number of post inside a thread user
5998
 */
5999
function count_number_of_post_for_user_thread($thread_id, $user_id)
6000
{
6001
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6002
    $course_id = api_get_course_int_id();
6003
    $sql = "SELECT count(iid) as count
6004
            FROM $table_posts
6005
            WHERE c_id = $course_id AND
6006
                  thread_id=".(int) $thread_id.' AND
6007
                  poster_id = '.(int) $user_id.' AND visible = 1 ';
6008
    $result = Database::query($sql);
6009
    $count = 0;
6010
    if (Database::num_rows($result) > 0) {
6011
        $count = Database::fetch_array($result);
6012
        $count = $count['count'];
6013
    }
6014
6015
    return $count;
6016
}
6017
6018
/**
6019
 * This function retrieves information of statistical.
6020
 *
6021
 * @param int $thread_id
6022
 * @param int $user_id
6023
 * @param int $course_id
6024
 *
6025
 * @return array the information of statistical
6026
 *
6027
 * @author Jhon Hinojosa <[email protected]>,
6028
 *
6029
 * @version oct 2008, dokeos 1.8
6030
 */
6031
function get_statistical_information($thread_id, $user_id, $course_id)
6032
{
6033
    $result = [];
6034
    $courseInfo = api_get_course_info_by_id($course_id);
6035
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
6036
    $result['post'] = count_number_of_post_in_thread($thread_id);
6037
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
6038
6039
    return $result;
6040
}
6041
6042
/**
6043
 * This function return the posts inside a thread from a given user.
6044
 *
6045
 * @param string $course_code
6046
 * @param int    $thread_id
6047
 * @param int    $user_id
6048
 *
6049
 * @return array posts inside a thread
6050
 *
6051
 * @author Jhon Hinojosa <[email protected]>,
6052
 *
6053
 * @version oct 2008, dokeos 1.8
6054
 */
6055
function get_thread_user_post($course_code, $thread_id, $user_id)
6056
{
6057
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6058
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
6059
    $thread_id = (int) $thread_id;
6060
    $user_id = (int) $user_id;
6061
    $course_info = api_get_user_info($course_code);
6062
    $course_id = $course_info['real_id'];
6063
6064
    if (empty($course_id)) {
6065
        $course_id = api_get_course_int_id();
6066
    }
6067
    $sql = "SELECT * FROM $table_posts posts
6068
            LEFT JOIN  $table_users users
6069
                ON posts.poster_id=users.user_id
6070
            WHERE
6071
                posts.c_id = $course_id AND
6072
                posts.thread_id='$thread_id'
6073
                AND posts.poster_id='$user_id'
6074
            ORDER BY posts.post_id ASC";
6075
6076
    $result = Database::query($sql);
6077
    $post_list = [];
6078
    while ($row = Database::fetch_array($result)) {
6079
        $row['status'] = '1';
6080
        $post_list[] = $row;
6081
        $sql = "SELECT * FROM $table_posts posts
6082
                LEFT JOIN $table_users users
6083
                ON (posts.poster_id=users.user_id)
6084
                WHERE
6085
                    posts.c_id = $course_id AND
6086
                    posts.thread_id='$thread_id'
6087
                    AND posts.post_parent_id='".$row['post_id']."'
6088
                ORDER BY posts.post_id ASC";
6089
        $result2 = Database::query($sql);
6090
        while ($row2 = Database::fetch_array($result2)) {
6091
            $row2['status'] = '0';
6092
            $post_list[] = $row2;
6093
        }
6094
    }
6095
6096
    return $post_list;
6097
}
6098
6099
/**
6100
 * This function get the name of an thread by id.
6101
 *
6102
 * @param int $thread_id
6103
 *
6104
 * @return string
6105
 *
6106
 * @author Christian Fasanando
6107
 * @author Julio Montoya <[email protected]> Adding security
6108
 */
6109
function get_name_thread_by_id($thread_id)
6110
{
6111
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
6112
    $course_id = api_get_course_int_id();
6113
    $sql = "SELECT thread_title
6114
            FROM $t_forum_thread
6115
            WHERE c_id = $course_id AND thread_id = '".(int) $thread_id."' ";
6116
    $result = Database::query($sql);
6117
    $row = Database::fetch_array($result);
6118
6119
    return $row[0];
6120
}
6121
6122
/**
6123
 * This function gets all the post written by an user.
6124
 *
6125
 * @param int    $user_id
6126
 * @param string $course_code
6127
 *
6128
 * @return string
6129
 */
6130
function get_all_post_from_user($user_id, $course_code)
6131
{
6132
    $j = 0;
6133
    $forums = get_forums('', $course_code);
6134
    krsort($forums);
6135
    $forum_results = '';
6136
6137
    foreach ($forums as $forum) {
6138
        if (0 == $forum['visibility']) {
6139
            continue;
6140
        }
6141
        if ($j <= 4) {
6142
            $threads = get_threads($forum['forum_id']);
6143
6144
            if (is_array($threads)) {
6145
                $i = 0;
6146
                $hand_forums = '';
6147
                $post_counter = 0;
6148
                foreach ($threads as $thread) {
6149
                    if (0 == $thread['visibility']) {
6150
                        continue;
6151
                    }
6152
                    if ($i <= 4) {
6153
                        $post_list = get_thread_user_post_limit(
6154
                            $course_code,
6155
                            $thread['thread_id'],
6156
                            $user_id,
6157
                            1
6158
                        );
6159
                        $post_counter = count($post_list);
6160
                        if (is_array($post_list) && count($post_list) > 0) {
6161
                            $hand_forums .= '<div id="social-thread">';
6162
                            $hand_forums .= Display::return_icon(
6163
                                'thread.png',
6164
                                get_lang('Thread'),
6165
                                '',
6166
                                ICON_SIZE_MEDIUM
6167
                            );
6168
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
6169
                            $hand_forums .= '</div>';
6170
6171
                            foreach ($post_list as $posts) {
6172
                                $hand_forums .= '<div id="social-post">';
6173
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
6174
                                $hand_forums .= '<br / >';
6175
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
6176
                                $hand_forums .= '</div>';
6177
                                $hand_forums .= '<br / >';
6178
                            }
6179
                        }
6180
                    }
6181
                    $i++;
6182
                }
6183
                $forum_results .= '<div id="social-forum">';
6184
                $forum_results .= '<div class="clear"></div><br />';
6185
                $forum_results .= '<div id="social-forum-title">'.
6186
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum['forum_title'], STUDENT).
6187
                    '<div style="float:right;margin-top:-35px">
6188
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($course_code).'&forum='.$forum['forum_id'].' " >'.
6189
                    get_lang('See forum').'
6190
                        </a>
6191
                     </div></div>';
6192
                $forum_results .= '<br / >';
6193
                if ($post_counter > 0) {
6194
                    $forum_results .= $hand_forums;
6195
                }
6196
                $forum_results .= '</div>';
6197
            }
6198
            $j++;
6199
        }
6200
    }
6201
6202
    return $forum_results;
6203
}
6204
6205
/**
6206
 * @param string $course_code
6207
 * @param int    $thread_id
6208
 * @param int    $user_id
6209
 * @param int    $limit
6210
 *
6211
 * @return array
6212
 */
6213
function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
6214
{
6215
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6216
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
6217
6218
    $course_info = api_get_course_info($course_code);
6219
    $course_id = $course_info['real_id'];
6220
6221
    $sql = "SELECT * FROM $table_posts posts
6222
            LEFT JOIN  $table_users users
6223
                ON posts.poster_id=users.user_id
6224
            WHERE
6225
                posts.c_id = $course_id AND
6226
                posts.thread_id='".Database::escape_string($thread_id)."' AND
6227
                posts.poster_id='".Database::escape_string($user_id)."'
6228
            ORDER BY posts.post_id DESC LIMIT $limit ";
6229
    $result = Database::query($sql);
6230
    $post_list = [];
6231
    while ($row = Database::fetch_array($result)) {
6232
        $row['status'] = '1';
6233
        $post_list[] = $row;
6234
    }
6235
6236
    return $post_list;
6237
}
6238
6239
/**
6240
 * @param string $userId
6241
 * @param array  $courseInfo
6242
 * @param int    $sessionId
6243
 *
6244
 * @return array
6245
 */
6246
function getForumCreatedByUser($userId, $courseInfo, $sessionId)
6247
{
6248
    if (empty($userId) || empty($courseInfo)) {
6249
        return [];
6250
    }
6251
6252
    $courseId = $courseInfo['real_id'];
6253
    $items = api_get_item_property_list_by_tool_by_user(
6254
        $userId,
6255
        'forum',
6256
        $courseId,
6257
        $sessionId
6258
    );
6259
6260
    $forumList = [];
6261
    if (!empty($items)) {
6262
        foreach ($items as $forum) {
6263
            $forumInfo = get_forums(
6264
                $forum['ref'],
6265
                $courseInfo['code'],
6266
                true,
6267
                $sessionId
6268
            );
6269
            if (!empty($forumInfo) && isset($forumInfo['forum_title'])) {
6270
                $forumList[] = [
6271
                    $forumInfo['forum_title'],
6272
                    api_get_local_time($forum['insert_date']),
6273
                    api_get_local_time($forum['lastedit_date']),
6274
                ];
6275
            }
6276
        }
6277
    }
6278
6279
    return $forumList;
6280
}
6281
6282
/**
6283
 * This function builds an array of all the posts in a given thread
6284
 * where the key of the array is the post_id
6285
 * It also adds an element children to the array which itself is an array
6286
 * that contains all the id's of the first-level children.
6287
 *
6288
 * @return array containing all the information on the posts of a thread
6289
 *
6290
 * @author Patrick Cool <[email protected]>, Ghent University
6291
 */
6292
function calculate_children($rows)
6293
{
6294
    $sorted_rows = [0 => []];
6295
    if (!empty($rows)) {
6296
        foreach ($rows as $row) {
6297
            $rows_with_children[$row['post_id']] = $row;
6298
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
6299
        }
6300
6301
        $rows = $rows_with_children;
6302
        forumRecursiveSort($rows, $sorted_rows);
6303
        unset($sorted_rows[0]);
6304
    }
6305
6306
    return $sorted_rows;
6307
}
6308
6309
/**
6310
 * @param $rows
6311
 * @param $threads
6312
 * @param int $seed
6313
 * @param int $indent
6314
 */
6315
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
6316
{
6317
    if ($seed > 0) {
6318
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
6319
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
6320
        $indent++;
6321
    }
6322
6323
    if (isset($rows[$seed]['children'])) {
6324
        foreach ($rows[$seed]['children'] as $child) {
6325
            forumRecursiveSort($rows, $threads, $child, $indent);
6326
        }
6327
    }
6328
}
6329
6330
/**
6331
 * Update forum attachment data, used to update comment and post ID.
6332
 *
6333
 * @param array  $array    (field => value) to update forum attachment row
6334
 * @param attach $id       ID to find row to update
6335
 * @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...
6336
 *
6337
 * @return int number of affected rows
6338
 */
6339
function editAttachedFile($array, $id, $courseId = null)
6340
{
6341
    // Init variables
6342
    $setString = '';
6343
    $id = (int) $id;
6344
    $courseId = (int) $courseId;
6345
    if (empty($courseId)) {
6346
        // $courseId can be null, use api method
6347
        $courseId = api_get_course_int_id();
6348
    }
6349
    /*
6350
     * Check if Attachment ID and Course ID are greater than zero
6351
     * and array of field values is not empty
6352
     */
6353
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
6354
        foreach ($array as $key => &$item) {
6355
            $item = Database::escape_string($item);
6356
            $setString .= $key.' = "'.$item.'", ';
6357
        }
6358
        // Delete last comma
6359
        $setString = substr($setString, 0, strlen($setString) - 2);
6360
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6361
        $sql = "UPDATE $forumAttachmentTable
6362
                SET $setString WHERE c_id = $courseId AND id = $id";
6363
        $result = Database::query($sql);
6364
        if (false !== $result) {
6365
            $affectedRows = Database::affected_rows($result);
6366
            if ($affectedRows > 0) {
6367
                /*
6368
                 * If exist in $_SESSION variable, then delete them from it
6369
                 * because they would be deprecated
6370
                 */
6371
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
6372
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
6373
                }
6374
            }
6375
6376
            return $affectedRows;
6377
        }
6378
    }
6379
6380
    return 0;
6381
}
6382
6383
/**
6384
 * Return a table where the attachments will be set.
6385
 *
6386
 * @param int $postId Forum Post ID
6387
 *
6388
 * @return string The Forum Attachments Ajax Table
6389
 */
6390
function getAttachmentsAjaxTable($postId = 0)
6391
{
6392
    $postId = (int) $postId;
6393
    $courseId = api_get_course_int_id();
6394
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6395
    $fileDataContent = '';
6396
    // Update comment to show if form did not pass validation
6397
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
6398
        // 'file_ids is the name from forum attachment ajax form
6399
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
6400
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
6401
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
6402
            ) {
6403
                // If exist forum attachment then update into $_SESSION data
6404
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
6405
            }
6406
        }
6407
    }
6408
6409
    // Get data to fill into attachment files table
6410
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6411
        is_array($_SESSION['forum']['upload_file'][$courseId])
6412
    ) {
6413
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
6414
        foreach ($uploadedFiles as $k => $uploadedFile) {
6415
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
6416
                // Buil html table including an input with attachmentID
6417
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
6418
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
6419
                    $uploadedFile['delete'].'</td>'.
6420
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
6421
            } else {
6422
                /*
6423
                 * If attachment data is empty, then delete it from $_SESSION
6424
                 * because could generate and empty row into html table
6425
                 */
6426
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
6427
            }
6428
        }
6429
    }
6430
    $style = empty($fileDataContent) ? 'display: none;' : '';
6431
    // Forum attachment Ajax table
6432
    return '
6433
    <div class="control-group " style="'.$style.'">
6434
        <label class="control-label">'.get_lang('Attachments list').'</label>
6435
        <div class="controls">
6436
            <table id="attachmentFileList" class="files data_table span10">
6437
                <tr>
6438
                    <th>'.get_lang('Filename').'</th>
6439
                    <th>'.get_lang('Size').'</th>
6440
                    <th>'.get_lang('Status').'</th>
6441
                    <th>'.get_lang('Comment').'</th>
6442
                    <th>'.get_lang('Delete').'</th>
6443
                </tr>
6444
                '.$fileDataContent.'
6445
            </table>
6446
        </div>
6447
    </div>';
6448
}
6449
6450
/**
6451
 * Return an array of prepared attachment data to build forum attachment table
6452
 * Also, save this array into $_SESSION to do available the attachment data.
6453
 *
6454
 * @param int $forumId
6455
 * @param int $threadId
6456
 * @param int $postId
6457
 * @param int $attachId
6458
 * @param int $courseId
6459
 *
6460
 * @return array
6461
 */
6462
function getAttachedFiles(
6463
    $forumId,
6464
    $threadId,
6465
    $postId = 0,
6466
    $attachId = 0,
6467
    $courseId = 0
6468
) {
6469
    $forumId = (int) $forumId;
6470
    $courseId = (int) $courseId;
6471
    $attachId = (int) $attachId;
6472
    $postId = (int) $postId;
6473
    $threadId = !empty($threadId) ? (int) $threadId : isset($_REQUEST['thread']) ? (int) ($_REQUEST['thread']) : '';
6474
    if (empty($courseId)) {
6475
        // $courseId can be null, use api method
6476
        $courseId = api_get_course_int_id();
6477
    }
6478
    if (empty($forumId)) {
6479
        if (!empty($_REQUEST['forum'])) {
6480
            $forumId = (int) $_REQUEST['forum'];
6481
        } else {
6482
            // if forum ID is empty, cannot generate delete url
6483
6484
            return [];
6485
        }
6486
    }
6487
    // Check if exist at least one of them to filter forum attachment select query
6488
    if (empty($postId) && empty($attachId)) {
6489
        return [];
6490
    } elseif (empty($postId)) {
6491
        $filter = "AND iid = $attachId";
6492
    } elseif (empty($attachId)) {
6493
        $filter = "AND post_id = $postId";
6494
    } else {
6495
        $filter = "AND post_id = $postId AND iid = $attachId";
6496
    }
6497
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6498
    $sql = "SELECT iid, comment, filename, path, size
6499
            FROM $forumAttachmentTable
6500
            WHERE c_id = $courseId $filter";
6501
    $result = Database::query($sql);
6502
    $json = [];
6503
    if (false !== $result && Database::num_rows($result) > 0) {
6504
        while ($row = Database::fetch_array($result, 'ASSOC')) {
6505
            // name contains an URL to download attachment file and its filename
6506
            $json['name'] = Display::url(
6507
                api_htmlentities($row['filename']),
6508
                api_get_path(WEB_CODE_PATH).'forum/download.php?file='.$row['path'].'&'.api_get_cidreq(),
6509
                ['target' => '_blank', 'class' => 'attachFilename']
6510
            );
6511
            $json['id'] = $row['iid'];
6512
            $json['comment'] = $row['comment'];
6513
            // Format file size
6514
            $json['size'] = format_file_size($row['size']);
6515
            // Check if $row is consistent
6516
            if (!empty($row) && is_array($row)) {
6517
                // Set result as success and bring delete URL
6518
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded.'));
6519
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
6520
                $json['delete'] = Display::url(
6521
                    Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL),
6522
                    $url,
6523
                    ['class' => 'deleteLink']
6524
                );
6525
            } else {
6526
                // If not, set an exclamation result
6527
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
6528
            }
6529
            // Store array data into $_SESSION
6530
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
6531
        }
6532
    }
6533
6534
    return $json;
6535
}
6536
6537
/**
6538
 * Clear forum attachment data stored in $_SESSION,
6539
 * If is not defined post, it will clear all forum attachment data from course.
6540
 *
6541
 * @param int $postId   -1 : Clear all attachments from course stored in $_SESSION
6542
 *                      0 : Clear attachments from course, except from temporal post "0"
6543
 *                      but without delete them from file system and database
6544
 *                      Other values : Clear attachments from course except specified post
6545
 *                      and delete them from file system and database
6546
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
6547
 *
6548
 * @return array
6549
 */
6550
function clearAttachedFiles($postId = 0, $courseId = 0)
6551
{
6552
    // Init variables
6553
    $courseId = (int) $courseId;
6554
    $postId = (int) $postId;
6555
    $array = [];
6556
    if (empty($courseId)) {
6557
        // $courseId can be null, use api method
6558
        $courseId = api_get_course_int_id();
6559
    }
6560
    if (-1 === $postId) {
6561
        // If post ID is -1 then delete course's attachment data from $_SESSION
6562
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
6563
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
6564
            unset($_SESSION['forum']['upload_file'][$courseId]);
6565
        }
6566
    } else {
6567
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6568
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6569
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
6570
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
6571
                if (!in_array($attachId, $attachIds)) {
6572
                    // If attach ID is not into specified post, delete attachment
6573
                    // Save deleted attachment ID
6574
                    $array[] = $attachId;
6575
                    if (0 !== $postId) {
6576
                        // Post 0 is temporal, delete them from file system and DB
6577
                        delete_attachment(0, $attachId);
6578
                    }
6579
                    // Delete attachment data from $_SESSION
6580
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
6581
                }
6582
            }
6583
        }
6584
    }
6585
6586
    return $array;
6587
}
6588
6589
/**
6590
 * Returns an array of forum attachment ids into a course and forum post.
6591
 *
6592
 * @param int $postId
6593
 * @param int $courseId
6594
 *
6595
 * @return array
6596
 */
6597
function getAttachmentIdsByPostId($postId, $courseId = 0)
6598
{
6599
    $array = [];
6600
    $courseId = (int) $courseId;
6601
    $postId = (int) $postId;
6602
    if (empty($courseId)) {
6603
        // $courseId can be null, use api method
6604
        $courseId = api_get_course_int_id();
6605
    }
6606
    if ($courseId > 0) {
6607
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6608
        $sql = "SELECT id FROM $forumAttachmentTable
6609
                WHERE c_id = $courseId AND post_id = $postId";
6610
        $result = Database::query($sql);
6611
        if (false !== $result && Database::num_rows($result) > 0) {
6612
            while ($row = Database::fetch_array($result, 'ASSOC')) {
6613
                $array[] = $row['id'];
6614
            }
6615
        }
6616
    }
6617
6618
    return $array;
6619
}
6620
6621
/**
6622
 * Check if the forum category exists looking for its title.
6623
 *
6624
 * @param string $title     The forum category title
6625
 * @param int    $courseId  The course ID
6626
 * @param int    $sessionId Optional. The session ID
6627
 *
6628
 * @return bool
6629
 */
6630
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
6631
{
6632
    $sessionId = (int) $sessionId;
6633
    $courseId = (int) $courseId;
6634
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
6635
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
6636
6637
    $fakeFrom = "$forumCategoryTable fc
6638
        INNER JOIN $itemProperty ip ";
6639
6640
    if (0 === $sessionId) {
6641
        $fakeFrom .= '
6642
            ON (
6643
                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)
6644
            )
6645
        ';
6646
    } else {
6647
        $fakeFrom .= '
6648
            ON (
6649
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
6650
            )
6651
        ';
6652
    }
6653
6654
    $resultData = Database::select(
6655
        'fc.*',
6656
        $fakeFrom,
6657
        [
6658
            'where' => [
6659
                'ip.visibility != ? AND ' => 2,
6660
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
6661
                'fc.session_id = ? AND ' => $sessionId,
6662
                'fc.cat_title = ? AND ' => $title,
6663
                'fc.c_id = ?' => $courseId,
6664
            ],
6665
        ],
6666
        'first'
6667
    );
6668
6669
    if (empty($resultData)) {
6670
        return false;
6671
    }
6672
6673
    return $resultData;
6674
}
6675
6676
/**
6677
 * @param array $row
6678
 * @param bool  $addWrapper
6679
 *
6680
 * @return string
6681
 */
6682
function getPostStatus(CForumForum $forum, $row, $addWrapper = true)
6683
{
6684
    $statusIcon = '';
6685
    if ($forum->isModerated()) {
6686
        if ($addWrapper) {
6687
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
6688
        }
6689
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
6690
6691
        $addUrl = false;
6692
        $showStatus = false;
6693
        if (api_is_allowed_to_edit(false, true)) {
6694
            $addUrl = true;
6695
        } else {
6696
            if ($row['user_id'] == api_get_user_id()) {
6697
                $showStatus = true;
6698
            }
6699
        }
6700
6701
        $label = '';
6702
        $icon = '';
6703
        $buttonType = '';
6704
        switch ($row['status']) {
6705
            case CForumPost::STATUS_VALIDATED:
6706
                $label = get_lang('Validated');
6707
                $icon = 'check-circle';
6708
                $buttonType = 'success';
6709
6710
                break;
6711
            case CForumPost::STATUS_WAITING_MODERATION:
6712
                $label = get_lang('Waiting for moderation');
6713
                $icon = 'warning';
6714
                $buttonType = 'warning';
6715
6716
                break;
6717
            case CForumPost::STATUS_REJECTED:
6718
                $label = get_lang('Rejected');
6719
                $icon = 'minus-circle';
6720
                $buttonType = 'danger';
6721
6722
                break;
6723
        }
6724
6725
        if ($addUrl) {
6726
            $statusIcon .= Display::toolbarButton(
6727
                $label.'&nbsp;',
6728
                'javascript:void(0)',
6729
                $icon,
6730
                $buttonType,
6731
                ['class' => 'change_post_status']
6732
            );
6733
        } else {
6734
            if ($showStatus) {
6735
                $statusIcon .= Display::label(
6736
                    Display::returnFontAwesomeIcon($icon).$label,
6737
                    $buttonType
6738
                );
6739
            }
6740
        }
6741
6742
        if ($addWrapper) {
6743
            $statusIcon .= '</span>';
6744
        }
6745
    }
6746
6747
    return $statusIcon;
6748
}
6749
6750
/**
6751
 * @param CForumForum $forum
6752
 * @param int         $threadId
6753
 * @param int         $status
6754
 */
6755
function getCountPostsWithStatus($status, $forum, $threadId = null)
6756
{
6757
    $em = Database::getManager();
6758
    $criteria = Criteria::create();
6759
    $criteria
6760
        ->where(Criteria::expr()->eq('status', $status))
6761
        ->andWhere(Criteria::expr()->eq('cId', $forum->getCId()))
6762
        ->andWhere(Criteria::expr()->eq('visible', 1))
6763
    ;
6764
6765
    if (!empty($threadId)) {
6766
        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
6767
    }
6768
6769
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
6770
    $qb->select('count(p.iid)')
6771
        ->addCriteria($criteria);
6772
6773
    return $qb->getQuery()->getSingleScalarResult();
6774
}
6775
6776
/**
6777
 * @param CForumForum $forum
6778
 * @param CForumPost  $post
6779
 *
6780
 * @return bool
6781
 */
6782
function postIsEditableByStudent($forum, $post)
6783
{
6784
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6785
        return true;
6786
    }
6787
6788
    if (1 == $forum->isModerated()) {
6789
        if (null === $post->getStatus()) {
6790
            return true;
6791
        } else {
6792
            return in_array(
6793
                $post->getStatus(),
6794
                [
6795
                    CForumPost::STATUS_WAITING_MODERATION,
6796
                    CForumPost::STATUS_REJECTED,
6797
                ]
6798
            );
6799
        }
6800
    }
6801
6802
    return true;
6803
}
6804
6805
/**
6806
 * @param int $postId
6807
 *
6808
 * @return bool
6809
 */
6810
function savePostRevision($postId)
6811
{
6812
    $postData = get_post_information($postId);
6813
6814
    if (empty($postData)) {
6815
        return false;
6816
    }
6817
6818
    $userId = api_get_user_id();
6819
6820
    if ($postData['poster_id'] != $userId) {
6821
        return false;
6822
    }
6823
6824
    $status = (int) !postNeedsRevision($postId);
6825
    $extraFieldValue = new ExtraFieldValue('forum_post');
6826
    $params = [
6827
        'item_id' => $postId,
6828
        'extra_ask_for_revision' => ['extra_ask_for_revision' => $status],
6829
    ];
6830
    if (empty($status)) {
6831
        unset($params['extra_ask_for_revision']);
6832
    }
6833
    $extraFieldValue->saveFieldValues(
6834
        $params,
6835
        true,
6836
        false,
6837
        ['ask_for_revision']
6838
    );
6839
}
6840
6841
/**
6842
 * @param int $postId
6843
 *
6844
 * @return string
6845
 */
6846
function getPostRevision($postId)
6847
{
6848
    $extraFieldValue = new ExtraFieldValue('forum_post');
6849
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6850
        $postId,
6851
        'revision_language'
6852
    );
6853
    $revision = '';
6854
    if ($value && isset($value['value'])) {
6855
        $revision = $value['value'];
6856
    }
6857
6858
    return $revision;
6859
}
6860
6861
/**
6862
 * @param int $postId
6863
 *
6864
 * @return bool
6865
 */
6866
function postNeedsRevision($postId)
6867
{
6868
    $extraFieldValue = new ExtraFieldValue('forum_post');
6869
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6870
        $postId,
6871
        'ask_for_revision'
6872
    );
6873
    $hasRevision = false;
6874
    if ($value && isset($value['value'])) {
6875
        return 1 == $value['value'];
6876
    }
6877
6878
    return $hasRevision;
6879
}
6880
6881
/**
6882
 * @param int   $postId
6883
 * @param array $threadInfo
6884
 *
6885
 * @return string
6886
 */
6887
function getAskRevisionButton($postId, $threadInfo)
6888
{
6889
    if (false === api_get_configuration_value('allow_forum_post_revisions')) {
6890
        return '';
6891
    }
6892
6893
    $postId = (int) $postId;
6894
6895
    $status = 'btn-default';
6896
    if (postNeedsRevision($postId)) {
6897
        $status = 'btn-success';
6898
    }
6899
6900
    return Display::url(
6901
        get_lang('Ask for a revision'),
6902
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6903
        api_get_cidreq().'&action=ask_revision&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6904
        ['class' => "btn $status", 'title' => get_lang('Ask for a revision')]
6905
    );
6906
}
6907
6908
/**
6909
 * @param int   $postId
6910
 * @param array $threadInfo
6911
 *
6912
 * @return string
6913
 */
6914
function giveRevisionButton($postId, $threadInfo)
6915
{
6916
    $postId = (int) $postId;
6917
6918
    return Display::toolbarButton(
6919
        get_lang('Give revision'),
6920
        api_get_path(WEB_CODE_PATH).'forum/reply.php?'.api_get_cidreq().'&'.http_build_query(
6921
            [
6922
                'forum' => $threadInfo['forum_id'],
6923
                'thread' => $threadInfo['thread_id'],
6924
                'post' => $postId = (int) $postId,
6925
                'action' => 'replymessage',
6926
                'give_revision' => 1,
6927
            ]
6928
        ),
6929
        'reply',
6930
        'primary',
6931
        ['id' => "reply-to-post-{$postId}"]
6932
    );
6933
}
6934
6935
/**
6936
 * @param int   $postId
6937
 * @param array $threadInfo
6938
 *
6939
 * @return string
6940
 */
6941
function getReportButton($postId, $threadInfo)
6942
{
6943
    $postId = (int) $postId;
6944
6945
    return Display::url(
6946
        Display::returnFontAwesomeIcon('flag'),
6947
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6948
        api_get_cidreq().'&action=report&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6949
        ['class' => 'btn btn-danger', 'title' => get_lang('Report')]
6950
    );
6951
}
6952
6953
/**
6954
 * @return bool
6955
 */
6956
function reportAvailable()
6957
{
6958
    $extraFieldValue = new ExtraFieldValue('course');
6959
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6960
        api_get_course_int_id(),
6961
        'allow_forum_report_button'
6962
    );
6963
    $allowReport = false;
6964
    if ($value && isset($value['value']) && 1 == $value['value']) {
6965
        $allowReport = true;
6966
    }
6967
6968
    return $allowReport;
6969
}
6970
6971
/**
6972
 * @return array
6973
 */
6974
function getReportRecipients()
6975
{
6976
    $extraFieldValue = new ExtraFieldValue('course');
6977
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6978
        api_get_course_int_id(),
6979
        'forum_report_recipients'
6980
    );
6981
    $users = [];
6982
    if ($value && isset($value['value'])) {
6983
        $usersType = explode(';', $value['value']);
6984
6985
        foreach ($usersType as $type) {
6986
            switch ($type) {
6987
                case 'teachers':
6988
                    $teachers = CourseManager::get_teacher_list_from_course_code(api_get_course_id());
6989
                    if (!empty($teachers)) {
6990
                        $users = array_merge($users, array_column($teachers, 'user_id'));
6991
                    }
6992
6993
                break;
6994
                case 'admins':
6995
                    $admins = UserManager::get_all_administrators();
6996
                    if (!empty($admins)) {
6997
                        $users = array_merge($users, array_column($admins, 'user_id'));
6998
                    }
6999
7000
                    break;
7001
                case 'community_managers':
7002
                    $managers = api_get_configuration_value('community_managers_user_list');
7003
                    if (!empty($managers) && isset($managers['users'])) {
7004
                        $users = array_merge($users, $managers['users']);
7005
                    }
7006
7007
                    break;
7008
            }
7009
        }
7010
7011
        $users = array_unique(array_filter($users));
7012
    }
7013
7014
    return $users;
7015
}
7016
7017
/**
7018
 * @param int   $postId
7019
 * @param array $forumInfo
7020
 * @param array $threadInfo
7021
 *
7022
 * @return bool
7023
 */
7024
function reportPost($postId, $forumInfo, $threadInfo)
7025
{
7026
    if (!reportAvailable()) {
7027
        return false;
7028
    }
7029
7030
    if (empty($forumInfo) || empty($threadInfo)) {
7031
        return false;
7032
    }
7033
7034
    $postId = (int) $postId;
7035
7036
    $postData = get_post_information($postId);
7037
    $currentUser = api_get_user_info();
7038
7039
    if (!empty($postData)) {
7040
        $users = getReportRecipients();
7041
        if (!empty($users)) {
7042
            $url = api_get_path(WEB_CODE_PATH).
7043
                'forum/viewthread.php?forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'].'&'.api_get_cidreq().'&post_id='.$postId.'#post_id_'.$postId;
7044
            $postLink = Display::url(
7045
                $postData['post_title'],
7046
                $url
7047
            );
7048
            $subject = get_lang('Post reported');
7049
            $content = sprintf(
7050
                get_lang('User %s has reported the message %s in the forum %s'),
7051
                $currentUser['complete_name'],
7052
                $postLink,
7053
                $forumInfo['forum_title']
7054
            );
7055
            foreach ($users as $userId) {
7056
                MessageManager::send_message_simple($userId, $subject, $content);
7057
            }
7058
        }
7059
    }
7060
}
7061