Passed
Push — master ( 50baa5...748ce8 )
by Julito
08:05
created

get_post_information()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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