Passed
Push — master ( ff47af...4fe9ef )
by Julito
08:21
created

get_forums()   D

Complexity

Conditions 16
Paths 2

Size

Total Lines 209
Code Lines 110

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 110
nc 2
nop 4
dl 0
loc 209
rs 4.4532
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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