Passed
Push — master ( 30e6c9...28eb1d )
by Julito
12:06 queued 13s
created

newThread()   F

Complexity

Conditions 29
Paths 4896

Size

Total Lines 250
Code Lines 165

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 29
eloc 165
nc 4896
nop 3
dl 0
loc 250
rs 0
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
        $category = new CForumCategory();
658
        $category
659
            ->setCatTitle($clean_cat_title)
660
            ->setCatComment(isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '')
661
            ->setCatOrder($new_max)
662
            ->setCId($course_id)
663
            ->setSessionId($session_id)
664
        ;
665
        $user = api_get_user_entity(api_get_user_id());
666
        $course = api_get_course_entity($course_id);
667
        $session = api_get_session_entity($session_id);
668
669
        $repo->addResourceToCourse($category, ResourceLink::VISIBILITY_PUBLISHED, $user, $course, $session);
670
        $repo->getEntityManager()->persist($category);
671
        $repo->getEntityManager()->flush();
672
673
        $last_id = $category->getIid();
674
675
        if ($last_id > 0) {
676
            $sql = "UPDATE $table_categories SET cat_id = $last_id WHERE iid = $last_id";
677
            Database::query($sql);
678
679
            /*api_item_property_update(
680
                $courseInfo,
681
                TOOL_FORUM_CATEGORY,
682
                $last_id,
683
                'ForumCategoryAdded',
684
                api_get_user_id()
685
            );
686
            api_set_default_visibility(
687
                $last_id,
688
                TOOL_FORUM_CATEGORY,
689
                0,
690
                $courseInfo
691
            );*/
692
        }
693
        $return_message = get_lang('The forum category has been added');
694
695
        $logInfo = [
696
            'tool' => TOOL_FORUM,
697
            'tool_id' => 0,
698
            'tool_id_detail' => 0,
699
            'action' => 'new-forumcategory',
700
            'action_details' => 'forumcategory',
701
            'info' => $clean_cat_title,
702
        ];
703
        Event::registerLog($logInfo);
704
705
        $values['item_id'] = $last_id;
706
    }
707
708
    $extraFieldValue = new ExtraFieldValue('forum_category');
709
    $extraFieldValue->saveFieldValues($values);
710
711
    if ($showMessage) {
712
        Display::addFlash(Display::return_message($return_message, 'confirmation'));
713
    }
714
715
    return $last_id;
716
}
717
718
/**
719
 * This function stores the forum in the database. The new forum is added to the end.
720
 *
721
 * @param array $values
722
 * @param array $courseInfo
723
 * @param bool  $returnId
724
 *
725
 * @return string language variable
726
 */
727
function store_forum($values, $courseInfo = [], $returnId = false)
728
{
729
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
730
    $courseId = $courseInfo['real_id'];
731
    $session_id = api_get_session_id();
732
    $group_id = api_get_group_id();
733
    if (isset($values['group_id']) && !empty($values['group_id'])) {
734
        $group_id = $values['group_id'];
735
    }
736
    $groupInfo = [];
737
    if (!empty($group_id)) {
738
        $groupInfo = GroupManager::get_group_properties($group_id);
739
    }
740
741
    $table_forums = Database::get_course_table(TABLE_FORUM);
742
743
    // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
744
    if (is_null($values['forum_category'])) {
745
        $new_max = null;
746
    } else {
747
        $sql = "SELECT MAX(forum_order) as sort_max
748
                FROM $table_forums
749
                WHERE
750
                    c_id = $courseId AND
751
                    forum_category='".Database::escape_string($values['forum_category'])."'";
752
        $result = Database::query($sql);
753
        $row = Database::fetch_array($result);
754
        $new_max = $row['sort_max'] + 1;
755
    }
756
757
    // Forum images
758
    $has_attachment = false;
759
    $image_moved = true;
760
    if (!empty($_FILES['picture']['name'])) {
761
        $upload_ok = process_uploaded_file($_FILES['picture']);
762
        $has_attachment = true;
763
    }
764
765
    // Remove existing picture if it was requested.
766
    if (!empty($_POST['remove_picture'])) {
767
        delete_forum_image($values['forum_id']);
768
    }
769
770
    $new_file_name = '';
771
    if (isset($upload_ok)) {
772
        if ($has_attachment) {
773
            $course_dir = $courseInfo['path'].'/upload/forum/images';
774
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
775
            $updir = $sys_course_path.$course_dir;
776
            // Try to add an extension to the file if it hasn't one.
777
            $new_file_name = add_ext_on_mime(
778
                Database::escape_string($_FILES['picture']['name']),
779
                $_FILES['picture']['type']
780
            );
781
            if (!filter_extension($new_file_name)) {
782
                //Display::addFlash(Display::return_message(get_lang('File upload failed: this file extension or file type is prohibited'), 'error'));
783
                $image_moved = false;
784
            } else {
785
                $file_extension = explode('.', $_FILES['picture']['name']);
786
                $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
787
                $new_file_name = uniqid('').'.'.$file_extension;
788
                $new_path = $updir.'/'.$new_file_name;
789
                $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
790
                // Storing the attachments if any
791
                if ($result) {
792
                    $image_moved = true;
793
                }
794
            }
795
        }
796
    }
797
798
    $repo = Container::getForumRepository();
799
800
    if (!isset($values['forum_id'])) {
801
        $forum = new CForumForum();
802
        $forum
803
            ->setCId($courseId)
804
            ->setSessionId($session_id)
805
            ->setForumOrder(isset($new_max) ? $new_max : null)
806
        ;
807
    } else {
808
        $forum = $repo->find($values['forum_id']);
809
    }
810
811
    $forumCategory = null;
812
    if (!empty($values['forum_category'])) {
813
        $repoForumCategory = Container::getForumCategoryRepository();
814
        $forumCategory = $repoForumCategory->find($values['forum_category']);
815
    }
816
    //'forum_image' => $new_file_name,
817
    $forum
818
        ->setForumTitle($values['forum_title'])
819
        ->setForumComment($values['forum_comment'] ?? null)
820
        ->setForumCategory($forumCategory)
821
        ->setAllowAnonymous($values['allow_anonymous_group']['allow_anonymous'] ?? null)
822
        ->setAllowEdit($values['students_can_edit_group']['students_can_edit'] ?? null)
823
        ->setApprovalDirectPost($values['approval_direct_group']['approval_direct'] ?? null)
824
        ->setAllowAttachments($values['allow_attachments_group']['allow_attachments'] ?? null)
825
        ->setAllowNewThreads($values['allow_new_threads_group']['allow_new_threads'] ?? null)
826
        ->setDefaultView($values['default_view_type_group']['default_view_type'] ?? null)
827
        ->setForumOfGroup($values['group_forum'] ?? null)
828
        ->setForumGroupPublicPrivate($values['public_private_group_forum_group']['public_private_group_forum'] ?? null)
829
        ->setModerated($values['moderated']['moderated'] ?? null)
830
        ->setStartTime(!empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null)
831
        ->setEndTime(!empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null)
832
        ->setSessionId($session_id)
833
        ->setLpId($values['lp_id'] ?? 0)
834
    ;
835
836
    $user = api_get_user_entity(api_get_user_id());
837
    $course = api_get_course_entity($courseId);
838
    $session = api_get_session_entity($session_id);
839
840
    if (isset($values['forum_id'])) {
841
        // Edit
842
        $repo->getEntityManager()->persist($forum);
843
        $repo->getEntityManager()->flush();
844
845
        if (isset($upload_ok)) {
846
            if ($has_attachment) {
847
                //$params['forum_image'] = $new_file_name;
848
            }
849
        }
850
851
        if (isset($values['remove_picture']) && $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
 * @return CForumThread[]
2098
 */
2099
function get_threads($forum_id, $courseId = null, $sessionId = null)
2100
{
2101
    $repo = Container::getForumThreadRepository();
2102
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
2103
    $course = api_get_course_entity($courseId);
2104
    $session = api_get_session_entity($sessionId);
2105
2106
    $qb = $repo->getResourcesByCourse($course, $session);
2107
2108
    /*$qb->andWhere('resource.forumCategory = :catId')
2109
        ->setParameter('catId', $cat_id);
2110
    */
2111
    return $qb->getQuery()->getResult();
2112
2113
2114
2115
    $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...
2116
    $sessionId = $sessionId !== null ? (int) $sessionId : api_get_session_id();
2117
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2118
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2119
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2120
2121
    $courseId = $courseId !== null ? (int) $courseId : api_get_course_int_id();
2122
    $groupInfo = GroupManager::get_group_properties($groupId);
2123
    $groupCondition = '';
2124
2125
    if (!empty($groupInfo)) {
2126
        $groupIid = $groupInfo['iid'];
2127
        $groupCondition = " AND item_properties.to_group_id = '$groupIid' ";
2128
    }
2129
2130
    $sessionCondition = api_get_session_condition(
2131
        $sessionId,
2132
        true,
2133
        false,
2134
        'item_properties.session_id'
2135
    );
2136
2137
    // important note:  it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
2138
    // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
2139
    // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
2140
    // This is why it is added to the end of the field selection
2141
    $sql = "SELECT DISTINCT
2142
                item_properties.*,
2143
                users.firstname,
2144
                users.lastname,
2145
                users.user_id,
2146
                thread.locked as locked,
2147
                thread.*
2148
            FROM $table_threads thread
2149
            INNER JOIN $table_item_property item_properties
2150
            ON
2151
                thread.thread_id = item_properties.ref AND
2152
                item_properties.c_id = thread.c_id AND
2153
                item_properties.tool = '".TABLE_FORUM_THREAD."'
2154
                $groupCondition
2155
                $sessionCondition
2156
            LEFT JOIN $table_users users
2157
                ON thread.thread_poster_id = users.user_id
2158
            WHERE
2159
                item_properties.visibility='1' AND
2160
                thread.forum_id = ".intval($forum_id)." AND
2161
                thread.c_id = $courseId
2162
            ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
2163
2164
    if (api_is_allowed_to_edit()) {
2165
        $sql = "SELECT DISTINCT
2166
                    item_properties.*,
2167
                    users.firstname,
2168
                    users.lastname,
2169
                    users.user_id,
2170
                    thread.locked as locked,
2171
                    thread.*
2172
                FROM $table_threads thread
2173
                INNER JOIN $table_item_property item_properties
2174
                ON
2175
                    thread.thread_id = item_properties.ref AND
2176
                    item_properties.c_id = thread.c_id AND
2177
                    item_properties.tool = '".TABLE_FORUM_THREAD."'
2178
                    $groupCondition
2179
                    $sessionCondition
2180
                LEFT JOIN $table_users users
2181
                    ON thread.thread_poster_id=users.user_id
2182
                WHERE
2183
                    item_properties.visibility<>2 AND
2184
                    thread.forum_id = ".intval($forum_id)." AND
2185
                    thread.c_id = $courseId
2186
                ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
2187
    }
2188
    $result = Database::query($sql);
2189
    $list = [];
2190
    $alreadyAdded = [];
2191
    while ($row = Database::fetch_array($result, 'ASSOC')) {
2192
        if (in_array($row['thread_id'], $alreadyAdded)) {
2193
            continue;
2194
        }
2195
        $list[] = $row;
2196
        $alreadyAdded[] = $row['thread_id'];
2197
    }
2198
2199
    return $list;
2200
}
2201
2202
/**
2203
 * Get a thread by Id and course id.
2204
 *
2205
 * @param int $threadId the thread Id
2206
 * @param int $cId      the course id
2207
 *
2208
 * @return array containing all the information about the thread
2209
 */
2210
function getThreadInfo($threadId, $cId)
2211
{
2212
    $repo = Database::getManager()->getRepository('ChamiloCourseBundle:CForumThread');
2213
    $forumThread = $repo->findOneBy(['threadId' => $threadId, 'cId' => $cId]);
2214
2215
    $thread = [];
2216
    if ($forumThread) {
2217
        $thread['threadId'] = $forumThread->getThreadId();
2218
        $thread['threadTitle'] = $forumThread->getThreadTitle();
2219
        $thread['forumId'] = $forumThread->getForum() ? $forumThread->getForum()->getIid() : 0;
2220
        $thread['sessionId'] = $forumThread->getSessionId();
2221
        $thread['threadSticky'] = $forumThread->getThreadSticky();
2222
        $thread['locked'] = $forumThread->getLocked();
2223
        $thread['threadTitleQualify'] = $forumThread->getThreadTitleQualify();
2224
        $thread['threadQualifyMax'] = $forumThread->getThreadQualifyMax();
2225
        $thread['threadCloseDate'] = $forumThread->getThreadCloseDate();
2226
        $thread['threadWeight'] = $forumThread->getThreadWeight();
2227
        $thread['threadPeerQualify'] = $forumThread->isThreadPeerQualify();
2228
    }
2229
2230
    return $thread;
2231
}
2232
2233
/**
2234
 * Retrieve all posts of a given thread.
2235
 *
2236
 * @param CForumForum  $forum
2237
 * @param int    $threadId       The thread ID
2238
 * @param string $orderDirection Optional. The direction for sort the posts
2239
 * @param bool   $recursive      Optional. If the list is recursive
2240
 * @param int    $postId         Optional. The post ID for recursive list
2241
 * @param int    $depth          Optional. The depth to indicate the indent
2242
 *
2243
 * @todo move to a repository
2244
 *
2245
 * @return array containing all the information about the posts of a given thread
2246
 */
2247
function getPosts(
2248
    CForumForum $forum,
2249
    $threadId,
2250
    $orderDirection = 'ASC',
2251
    $recursive = false,
2252
    $postId = null,
2253
    $depth = -1
2254
) {
2255
    $em = Database::getManager();
2256
2257
    if (api_is_allowed_to_edit(false, true)) {
2258
        $visibleCriteria = Criteria::expr()->neq('visible', 2);
2259
    } else {
2260
        $visibleCriteria = Criteria::expr()->eq('visible', 1);
2261
    }
2262
2263
    $criteria = Criteria::create();
2264
    $criteria
2265
        ->where(Criteria::expr()->eq('thread', $threadId))
2266
        ->andWhere(Criteria::expr()->eq('cId', $forum->getCId()))
2267
        ->andWhere($visibleCriteria)
2268
    ;
2269
2270
    $groupId = api_get_group_id();
2271
    $groupInfo = GroupManager::get_group_properties($groupId);
2272
    $filterModerated = true;
2273
2274
    if (empty($groupId)) {
2275
        if (api_is_allowed_to_edit()) {
2276
            $filterModerated = false;
2277
        }
2278
    } else {
2279
        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo) ||
2280
            api_is_allowed_to_edit(false, true)
2281
        ) {
2282
            $filterModerated = false;
2283
        }
2284
    }
2285
2286
    if ($recursive) {
2287
        $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
2288
    }
2289
2290
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
2291
    $qb->select('p')
2292
        ->addCriteria($criteria)
2293
        ->addOrderBy('p.postId', $orderDirection);
2294
2295
    if ($filterModerated && $forum->isModerated() == 1) {
2296
        if (!api_is_allowed_to_edit(false, true)) {
2297
            $userId = api_get_user_id();
2298
            $qb->andWhere(
2299
                "p.status = 1 OR
2300
                    (p.status = ".CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
2301
                    (p.status = ".CForumPost::STATUS_REJECTED." AND p.posterId = $userId) OR
2302
                    (p.status IS NULL AND p.posterId = $userId)
2303
                    "
2304
            );
2305
        }
2306
    }
2307
2308
    $posts = $qb->getQuery()->getResult();
2309
    $depth++;
2310
2311
    $list = [];
2312
    /** @var CForumPost $post */
2313
    foreach ($posts as $post) {
2314
        $postInfo = [
2315
            'iid' => $post->getIid(),
2316
            'c_id' => $post->getCId(),
2317
            'post_id' => $post->getPostId(),
2318
            'post_title' => $post->getPostTitle(),
2319
            'post_text' => $post->getPostText(),
2320
            'thread_id' => $post->getThread() ? $post->getThread()->getIid() : 0,
2321
            'forum_id' => $post->getForumId(),
2322
            'poster_id' => $post->getPosterId(),
2323
            'poster_name' => $post->getPosterName(),
2324
            'post_date' => $post->getPostDate(),
2325
            'post_notification' => $post->getPostNotification(),
2326
            'post_parent_id' => $post->getPostParentId(),
2327
            'visible' => $post->getVisible(),
2328
            'status' => $post->getStatus(),
2329
            'indent_cnt' => $depth,
2330
        ];
2331
2332
        $posterId = $post->getPosterId();
2333
        if (!empty($posterId)) {
2334
            $user = api_get_user_entity($posterId);
2335
            if ($user) {
2336
                $postInfo['user_id'] = $user->getUserId();
2337
                $postInfo['username'] = $user->getUsername();
2338
                $postInfo['username_canonical'] = $user->getUsernameCanonical();
2339
                $postInfo['lastname'] = $user->getLastname();
2340
                $postInfo['firstname'] = $user->getFirstname();
2341
                $postInfo['complete_name'] = UserManager::formatUserFullName($user);
2342
            }
2343
        }
2344
2345
        $list[] = $postInfo;
2346
2347
        if (!$recursive) {
2348
            continue;
2349
        }
2350
        $list = array_merge(
2351
            $list,
2352
            getPosts(
2353
                $forum,
2354
                $threadId,
2355
                $orderDirection,
2356
                $recursive,
2357
                $post->getPostId(),
2358
                $depth
2359
            )
2360
        );
2361
    }
2362
2363
    return $list;
2364
}
2365
2366
/**
2367
 * This function retrieves all the information of a post.
2368
 *
2369
 * @param int $post_id integer that indicates the forum
2370
 *
2371
 * @return array returns
2372
 *
2373
 * @author Patrick Cool <[email protected]>, Ghent University
2374
 *
2375
 * @version february 2006, dokeos 1.8
2376
 */
2377
function get_post_information($post_id)
2378
{
2379
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
2380
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2381
    $course_id = api_get_course_int_id();
2382
    $post_id = (int) $post_id;
2383
2384
    if (empty($post_id)) {
2385
        return [];
2386
    }
2387
2388
    $sql = "SELECT posts.*, email FROM ".$table_posts." posts, ".$table_users." users
2389
            WHERE
2390
                c_id = $course_id AND
2391
                posts.poster_id=users.user_id AND
2392
                posts.post_id = ".$post_id;
2393
    $result = Database::query($sql);
2394
    $row = Database::fetch_array($result, 'ASSOC');
2395
2396
    return $row;
2397
}
2398
2399
/**
2400
 * This function retrieves all the information of a thread.
2401
 *
2402
 * @param int $forumId
2403
 * @param $thread_id integer that indicates the forum
2404
 * @param int|null $sessionId Optional. If is null then it is considered the current session
2405
 *
2406
 * @return array returns
2407
 *
2408
 * @author Patrick Cool <[email protected]>, Ghent University
2409
 *
2410
 * @version february 2006, dokeos 1.8
2411
 */
2412
function get_thread_information($forumId, $thread_id, $sessionId = null)
2413
{
2414
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2415
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2416
    $thread_id = intval($thread_id);
2417
    $sessionId = $sessionId !== null ? intval($sessionId) : api_get_session_id();
2418
    $sessionCondition = api_get_session_condition(
2419
        $sessionId,
2420
        true,
2421
        false,
2422
        'threads.session_id'
2423
    );
2424
    $forumCondition = '';
2425
    if (!empty($forumId)) {
2426
        $forumId = (int) $forumId;
2427
        $forumCondition = " threads.forum_id = $forumId AND ";
2428
    }
2429
    $sql = "SELECT * FROM $table_item_property item_properties
2430
            INNER JOIN
2431
            $table_threads threads
2432
            ON (item_properties.ref = threads.thread_id AND threads.c_id = item_properties.c_id)
2433
            WHERE
2434
                $forumCondition
2435
                item_properties.tool= '".TOOL_FORUM_THREAD."' AND
2436
                threads.thread_id = $thread_id
2437
                $sessionCondition
2438
            ";
2439
2440
    $result = Database::query($sql);
2441
    $row = Database::fetch_assoc($result);
2442
2443
    return $row;
2444
}
2445
2446
/**
2447
 * This function retrieves forum thread users details.
2448
 *
2449
 * @param   int Thread ID
2450
 * @param   string  Course DB name (optional)
2451
 *
2452
 * @return Doctrine\DBAL\Driver\Statement|null array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2453
 *
2454
 * @author Christian Fasanando <[email protected]>,
2455
 *
2456
 * @todo     this function need to be improved
2457
 *
2458
 * @version octubre 2008, dokeos 1.8
2459
 */
2460
function get_thread_users_details($thread_id)
2461
{
2462
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2463
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2464
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2465
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2466
2467
    $course_id = api_get_course_int_id();
2468
2469
    $is_western_name_order = api_is_western_name_order();
2470
    if ($is_western_name_order) {
2471
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2472
    } else {
2473
        $orderby = 'ORDER BY user.lastname, user.firstname';
2474
    }
2475
2476
    if (api_get_session_id()) {
2477
        $session_info = api_get_session_info(api_get_session_id());
2478
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2479
        //not showing coaches
2480
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2481
                FROM $t_posts p, $t_users user, $t_session_rel_user session_rel_user_rel_course
2482
                WHERE
2483
                    p.poster_id = user.id AND
2484
                    user.id = session_rel_user_rel_course.user_id AND
2485
                    session_rel_user_rel_course.status<>'2' AND
2486
                    session_rel_user_rel_course.user_id NOT IN ($user_to_avoid) AND
2487
                    p.thread_id = ".intval($thread_id)." AND
2488
                    session_id = ".api_get_session_id()." AND
2489
                    p.c_id = $course_id AND
2490
                    session_rel_user_rel_course.c_id = ".$course_id." $orderby ";
2491
    } else {
2492
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2493
                FROM $t_posts p, $t_users user, $t_course_user course_user
2494
                WHERE
2495
                    p.poster_id = user.id
2496
                    AND user.id = course_user.user_id
2497
                    AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2498
                    AND p.thread_id = ".intval($thread_id)."
2499
                    AND course_user.status NOT IN('1') AND
2500
                    p.c_id = $course_id AND
2501
                    course_user.c_id = ".$course_id." $orderby";
2502
    }
2503
    $result = Database::query($sql);
2504
2505
    return $result;
2506
}
2507
2508
/**
2509
 * This function retrieves forum thread users qualify.
2510
 *
2511
 * @param   int Thread ID
2512
 * @param   string  Course DB name (optional)
2513
 *
2514
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2515
 *
2516
 * @author Jhon Hinojosa
2517
 *
2518
 * @todo     this function need to be improved
2519
 */
2520
function get_thread_users_qualify($thread_id)
2521
{
2522
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2523
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2524
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2525
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2526
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2527
2528
    $course_id = api_get_course_int_id();
2529
    $sessionId = api_get_session_id();
2530
2531
    $is_western_name_order = api_is_western_name_order();
2532
    if ($is_western_name_order) {
2533
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2534
    } else {
2535
        $orderby = 'ORDER BY user.lastname, user.firstname';
2536
    }
2537
2538
    if ($sessionId) {
2539
        $session_info = api_get_session_info($sessionId);
2540
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2541
        //not showing coaches
2542
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2543
                FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
2544
                WHERE poster_id = user.id
2545
                    AND post.poster_id = qualify.user_id
2546
                    AND user.id = scu.user_id
2547
                    AND scu.status<>'2'
2548
                    AND scu.user_id NOT IN ($user_to_avoid)
2549
                    AND qualify.thread_id = ".intval($thread_id)."
2550
                    AND post.thread_id = ".intval($thread_id)."
2551
                    AND scu.session_id = $sessionId
2552
                    AND scu.c_id = ".$course_id." AND
2553
                    qualify.c_id = $course_id AND
2554
                    post.c_id = $course_id
2555
                $orderby ";
2556
    } else {
2557
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2558
                FROM $t_posts post,
2559
                     $t_qualify qualify,
2560
                     $t_users user,
2561
                     $t_course_user course_user
2562
                WHERE
2563
                     post.poster_id = user.id
2564
                     AND post.poster_id = qualify.user_id
2565
                     AND user.id = course_user.user_id
2566
                     AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2567
                     AND qualify.thread_id = ".intval($thread_id)."
2568
                     AND post.thread_id = ".intval($thread_id)."
2569
                     AND course_user.status not in('1')
2570
                     AND course_user.c_id = $course_id
2571
                     AND qualify.c_id = $course_id
2572
                     AND post.c_id = $course_id
2573
                 $orderby ";
2574
    }
2575
    $result = Database::query($sql);
2576
2577
    return $result;
2578
}
2579
2580
/**
2581
 * This function retrieves forum thread users not qualify.
2582
 *
2583
 * @param   int Thread ID
2584
 * @param   string  Course DB name (optional)
2585
 *
2586
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2587
 *
2588
 * @author   Jhon Hinojosa<[email protected]>,
2589
 *
2590
 * @version oct 2008, dokeos 1.8
2591
 */
2592
function get_thread_users_not_qualify($thread_id)
2593
{
2594
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2595
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2596
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2597
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2598
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2599
2600
    $is_western_name_order = api_is_western_name_order();
2601
    if ($is_western_name_order) {
2602
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2603
    } else {
2604
        $orderby = 'ORDER BY user.lastname, user.firstname';
2605
    }
2606
2607
    $course_id = api_get_course_int_id();
2608
2609
    $sql1 = "SELECT user_id FROM  $t_qualify
2610
             WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
2611
    $result1 = Database::query($sql1);
2612
    $cad = '';
2613
    while ($row = Database::fetch_array($result1)) {
2614
        $cad .= $row['user_id'].',';
2615
    }
2616
    if ($cad == '') {
2617
        $cad = '0';
2618
    } else {
2619
        $cad = substr($cad, 0, strlen($cad) - 1);
2620
    }
2621
2622
    if (api_get_session_id()) {
2623
        $session_info = api_get_session_info(api_get_session_id());
2624
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2625
        //not showing coaches
2626
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2627
                FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
2628
                WHERE poster_id = user.id
2629
                    AND user.id NOT IN (".$cad.")
2630
                    AND user.id = session_rel_user_rel_course.user_id
2631
                    AND session_rel_user_rel_course.status<>'2'
2632
                    AND session_rel_user_rel_course.user_id NOT IN ($user_to_avoid)
2633
                    AND post.thread_id = ".intval($thread_id)."
2634
                    AND session_id = ".api_get_session_id()."
2635
                    AND session_rel_user_rel_course.c_id = $course_id AND post.c_id = $course_id $orderby ";
2636
    } else {
2637
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2638
                FROM $t_posts post, $t_users user,$t_course_user course_user
2639
                WHERE post.poster_id = user.id
2640
                AND user.id NOT IN (".$cad.")
2641
                AND user.id = course_user.user_id
2642
                AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2643
                AND post.thread_id = ".intval($thread_id)."
2644
                AND course_user.status not in('1')
2645
                AND course_user.c_id = $course_id AND post.c_id = $course_id  $orderby";
2646
    }
2647
    $result = Database::query($sql);
2648
2649
    return $result;
2650
}
2651
2652
/**
2653
 * This function retrieves all the information of a given forum_id.
2654
 *
2655
 * @param $forum_id integer that indicates the forum
2656
 *
2657
 * @return array returns
2658
 *
2659
 * @author Patrick Cool <[email protected]>, Ghent University
2660
 *
2661
 * @version february 2006, dokeos 1.8
2662
 *
2663
 * @deprecated this functionality is now moved to get_forums($forum_id)
2664
 */
2665
function get_forum_information($forum_id, $courseId = 0)
2666
{
2667
    $table_forums = Database::get_course_table(TABLE_FORUM);
2668
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2669
    $courseId = empty($courseId) ? api_get_course_int_id() : intval($courseId);
2670
    $forum_id = intval($forum_id);
2671
2672
    $sql = "SELECT *
2673
            FROM $table_forums forums
2674
            INNER JOIN $table_item_property item_properties
2675
            ON (forums.c_id = item_properties.c_id)
2676
            WHERE
2677
                item_properties.tool = '".TOOL_FORUM."' AND
2678
                item_properties.ref = '".$forum_id."' AND
2679
                forums.forum_id = '".$forum_id."' AND
2680
                forums.c_id = ".$courseId."
2681
            ";
2682
2683
    $result = Database::query($sql);
2684
    $row = Database::fetch_array($result, 'ASSOC');
2685
    $row['approval_direct_post'] = 0;
2686
    // We can't anymore change this option, so it should always be activated.
2687
2688
    return $row;
2689
}
2690
2691
/**
2692
 * This function retrieves all the information of a given forumcategory id.
2693
 *
2694
 * @param $cat_id integer that indicates the forum
2695
 *
2696
 * @return array returns if there are category or bool returns if there aren't category
2697
 *
2698
 * @author Patrick Cool <[email protected]>, Ghent University
2699
 *
2700
 * @version february 2006, dokeos 1.8
2701
 */
2702
function get_forumcategory_information($cat_id)
2703
{
2704
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
2705
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2706
2707
    $course_id = api_get_course_int_id();
2708
    $sql = "SELECT *
2709
            FROM $table_categories forumcategories
2710
            INNER JOIN $table_item_property item_properties
2711
            ON (forumcategories.c_id = item_properties.c_id)
2712
            WHERE
2713
                forumcategories.c_id = $course_id AND
2714
                item_properties.c_id = $course_id AND
2715
                item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
2716
                item_properties.ref='".Database::escape_string($cat_id)."' AND
2717
                forumcategories.cat_id='".Database::escape_string($cat_id)."'";
2718
    $result = Database::query($sql);
2719
    $row = Database::fetch_array($result);
2720
2721
    return $row;
2722
}
2723
2724
/**
2725
 * This function counts the number of forums inside a given category.
2726
 *
2727
 * @param int $cat_id the id of the forum category
2728
 *
2729
 * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
2730
 *      of visible forums, $countinvisible=1 would return the number of visible and invisible forums
2731
 *
2732
 * @return int the number of forums inside the given category
2733
 *
2734
 * @author Patrick Cool <[email protected]>, Ghent University
2735
 *
2736
 * @version february 2006, dokeos 1.8
2737
 */
2738
function count_number_of_forums_in_category($cat_id)
2739
{
2740
    $table_forums = Database::get_course_table(TABLE_FORUM);
2741
    $course_id = api_get_course_int_id();
2742
    $cat_id = (int) $cat_id;
2743
    $sql = "SELECT count(*) AS number_of_forums
2744
            FROM $table_forums
2745
            WHERE c_id = $course_id AND forum_category = $cat_id";
2746
    $result = Database::query($sql);
2747
    $row = Database::fetch_array($result);
2748
2749
    return $row['number_of_forums'];
2750
}
2751
2752
/**
2753
 * This function update a thread.
2754
 *
2755
 * @param array $values - The form Values
2756
 */
2757
function updateThread($values)
2758
{
2759
    if (!api_is_allowed_to_edit()) {
2760
        return '';
2761
    }
2762
2763
    $logInfo = [
2764
        'tool' => TOOL_FORUM,
2765
        'tool_id' => $values['forum_id'],
2766
        'tool_id_detail' => $values['thread_id'],
2767
        'action' => 'edit-thread',
2768
        'action_details' => 'thread',
2769
        'info' => $values['thread_title'],
2770
    ];
2771
    Event::registerLog($logInfo);
2772
2773
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
2774
    $courseId = api_get_course_int_id();
2775
    $courseCode = api_get_course_id();
2776
    $sessionId = api_get_session_id();
2777
2778
    // Simple update + set gradebook values to null
2779
    $params = [
2780
        'thread_title' => $values['thread_title'],
2781
        'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
2782
    ];
2783
    $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2784
    Database::update($threadTable, $params, $where);
2785
2786
    $id = $values['thread_id'];
2787
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
2788
        $courseCode,
2789
        LINK_FORUM_THREAD,
2790
        $id,
2791
        $sessionId
2792
    );
2793
    $linkId = $linkInfo['id'];
2794
    $em = Database::getManager();
2795
    $gradebookLink = null;
2796
    if (!empty($linkId)) {
2797
        $gradebookLink = $em->getRepository('ChamiloCoreBundle:GradebookLink')->find($linkId);
2798
    }
2799
2800
    // values 1 or 0
2801
    $check = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : false;
2802
    if ($check) {
2803
        $title = Security::remove_XSS(stripslashes($values['calification_notebook_title']));
2804
        $value = isset($values['numeric_calification']) ? intval($values['numeric_calification']) : 0;
2805
        $weight = isset($values['weight_calification']) ? floatval($values['weight_calification']) : 0;
2806
        $description = '';
2807
        // Update title
2808
        $params = [
2809
            'thread_title_qualify' => $values['calification_notebook_title'],
2810
            'thread_qualify_max' => api_float_val($values['numeric_calification']),
2811
            'thread_weight' => api_float_val($values['weight_calification']),
2812
            'thread_peer_qualify' => $values['thread_peer_qualify'],
2813
        ];
2814
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2815
        Database::update($threadTable, $params, $where);
2816
2817
        if (!$linkInfo) {
2818
            GradebookUtils::add_resource_to_course_gradebook(
2819
                $values['category_id'],
2820
                $courseCode,
2821
                LINK_FORUM_THREAD,
2822
                $id,
2823
                $title,
2824
                $weight,
2825
                $value,
2826
                $description,
2827
                1,
2828
                $sessionId
2829
            );
2830
        } else {
2831
            if ($gradebookLink) {
2832
                $gradebookLink->setWeight($weight);
2833
                $em->persist($gradebookLink);
2834
                $em->flush();
2835
            }
2836
        }
2837
    } else {
2838
        $params = [
2839
            'thread_title_qualify' => '',
2840
            'thread_qualify_max' => 0,
2841
            'thread_weight' => 0,
2842
            'thread_peer_qualify' => 0,
2843
        ];
2844
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2845
        Database::update($threadTable, $params, $where);
2846
2847
        if (!empty($linkInfo)) {
2848
            if ($gradebookLink) {
2849
                $em->remove($gradebookLink);
2850
                $em->flush();
2851
            }
2852
        }
2853
    }
2854
2855
    $message = get_lang('The post has been modified').'<br />';
2856
    Display::addFlash(Display::return_message($message, 'confirmation', false));
2857
}
2858
2859
/**
2860
 * This function stores a new thread. This is done through an entry in the forum_thread table AND
2861
 * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet)).
2862
 *
2863
 * @param array $current_forum
2864
 * @param array $values
2865
 * @param array $courseInfo
2866
 * @param bool  $showMessage
2867
 * @param int   $userId        Optional. The user ID
2868
 * @param int   $sessionId
2869
 *
2870
 * @return CForumThread
2871
 *
2872
 * @author Patrick Cool <[email protected]>, Ghent University
2873
 *
2874
 * @version february 2006, dokeos 1.8
2875
 */
2876
function store_thread(
2877
    CForumForum $forum,
2878
    $values,
2879
    $courseInfo = [],
2880
    $showMessage = true,
2881
    $userId = 0,
2882
    $sessionId = 0
2883
) {
2884
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
2885
    $userId = $userId ?: api_get_user_id();
2886
    $course_id = $courseInfo['real_id'];
2887
    $courseCode = $courseInfo['code'];
2888
    $groupId = api_get_group_id();
2889
    $groupInfo = GroupManager::get_group_properties($groupId);
2890
    $sessionId = $sessionId ?: api_get_session_id();
2891
2892
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2893
    $upload_ok = 1;
2894
    $has_attachment = false;
2895
    if (!empty($_FILES['user_upload']['name'])) {
2896
        $upload_ok = process_uploaded_file($_FILES['user_upload']);
2897
        $has_attachment = true;
2898
    }
2899
2900
    if (!$upload_ok) {
2901
        if ($showMessage) {
2902
            Display::addFlash(
2903
                Display::return_message(
2904
                    get_lang('No file was uploaded.'),
2905
                    'error',
2906
                    false
2907
                )
2908
            );
2909
        }
2910
2911
        return null;
2912
    }
2913
2914
    $post_date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
2915
    $visible = 1;
2916
    if ($forum->getApprovalDirectPost() == '1' && !api_is_allowed_to_edit(null, true)) {
2917
        $visible = 0; // The post has not been approved yet.
2918
    }
2919
    $clean_post_title = $values['post_title'];
2920
2921
    // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
2922
    $thread = new CForumThread();
2923
    $thread
2924
        ->setCId($course_id)
2925
        ->setThreadTitle($clean_post_title)
2926
        ->setForum($forum)
2927
        ->setThreadPosterId($userId)
2928
        ->setThreadPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2929
        ->setThreadDate($post_date)
2930
        ->setThreadSticky(isset($values['thread_sticky']) ? $values['thread_sticky'] : 0)
2931
        ->setThreadTitleQualify(
2932
            isset($values['calification_notebook_title']) ? $values['calification_notebook_title'] : null
2933
        )
2934
        ->setThreadQualifyMax(isset($values['numeric_calification']) ? (int)$values['numeric_calification'] : 0)
2935
        ->setThreadWeight(isset($values['weight_calification']) ? (int) $values['weight_calification'] : 0)
2936
        ->setThreadPeerQualify(isset($values['thread_peer_qualify']) ? (bool) $values['thread_peer_qualify'] : false)
2937
        ->setSessionId($sessionId)
2938
        ->setLpItemId(isset($values['lp_item_id']) ? (int) $values['lp_item_id'] : 0)
2939
    ;
2940
    $user = api_get_user_entity(api_get_user_id());
2941
    $course = api_get_course_entity($course_id);
2942
    $session = api_get_session_entity($sessionId);
2943
2944
    $repo = Container::getForumThreadRepository();
2945
    $em = $repo->getEntityManager();
2946
    //$em->persist($thread);
2947
    $resourceNode = $repo->createNodeForResource($thread, $user, $forum->getResourceNode());
2948
    $repo->addResourceNodeToCourse(
2949
        $resourceNode,
2950
        ResourceLink::VISIBILITY_PUBLISHED,
2951
        $course,
2952
        $session,
2953
        null
2954
    );
2955
    $em->flush();
2956
2957
    // Add option gradebook qualify.
2958
    if (isset($values['thread_qualify_gradebook']) &&
2959
        1 == $values['thread_qualify_gradebook']
2960
    ) {
2961
        // Add function gradebook.
2962
        $resourcename = stripslashes($values['calification_notebook_title']);
2963
        GradebookUtils::add_resource_to_course_gradebook(
2964
            $values['category_id'],
2965
            $courseCode,
2966
            5,
2967
            $thread->getIid(),
2968
            $resourcename,
2969
            $values['weight_calification'],
2970
            $values['numeric_calification'],
2971
            '',
2972
            0,
2973
            $sessionId
2974
        );
2975
    }
2976
2977
    if ($thread->getIid()) {
2978
        $thread->setThreadId($thread->getIid());
2979
        $em->persist($thread);
2980
        $em->flush();
2981
2982
        /*api_item_property_update(
2983
            $courseInfo,
2984
            TOOL_FORUM_THREAD,
2985
            $thread->getIid(),
2986
            'ForumThreadAdded',
2987
            $userId,
2988
            $groupInfo,
2989
            null,
2990
            null,
2991
            null,
2992
            $sessionId
2993
        );*/
2994
2995
        // If the forum properties tell that the posts have to be approved
2996
        // we have to put the whole thread invisible,
2997
        // because otherwise the students will see the thread and not the post
2998
        // in the thread.
2999
        // We also have to change $visible because the post itself has to be
3000
        // visible in this case (otherwise the teacher would have
3001
        // to make the thread visible AND the post.
3002
        // Default behaviour
3003
        /*api_set_default_visibility(
3004
            $thread->getIid(),
3005
            TOOL_FORUM_THREAD,
3006
            $groupId,
3007
            $courseInfo,
3008
            $sessionId,
3009
            $userId
3010
        );*/
3011
3012
        if ($visible == 0) {
3013
            /*api_item_property_update(
3014
                $courseInfo,
3015
                TOOL_FORUM_THREAD,
3016
                $thread->getIid(),
3017
                'invisible',
3018
                $userId,
3019
                $groupInfo
3020
            );*/
3021
            $visible = 1;
3022
        }
3023
3024
        $logInfo = [
3025
            'tool' => TOOL_FORUM,
3026
            'tool_id' => $values['forum_id'],
3027
            'tool_id_detail' => $thread->getIid(),
3028
            'action' => 'new-thread',
3029
            'action_details' => '',
3030
            'info' => $clean_post_title,
3031
        ];
3032
        Event::registerLog($logInfo);
3033
    }
3034
3035
    // We now store the content in the table_post table.
3036
    $post = new CForumPost();
3037
    $post
3038
        ->setCId($course_id)
3039
        ->setPostTitle($clean_post_title)
3040
        ->setPostText($values['post_text'])
3041
        ->setThread($thread)
3042
        ->setForumId($values['forum_id'])
3043
        ->setPosterId($userId)
3044
        ->setPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
3045
        ->setPostDate($post_date)
3046
        ->setPostNotification(isset($values['post_notification']) ? (int) $values['post_notification'] : null)
3047
        ->setPostParentId(null)
3048
        ->setVisible($visible)
3049
        ->setPostId(0)
3050
        ->setStatus(CForumPost::STATUS_VALIDATED);
3051
3052
    if ($forum->isModerated()) {
3053
        $post->setStatus(
3054
            api_is_course_admin() ? CForumPost::STATUS_VALIDATED : CForumPost::STATUS_WAITING_MODERATION
3055
        );
3056
    }
3057
3058
    $repo = Container::getForumPostRepository();
3059
    $em = $repo->getEntityManager();
3060
    $resourceNode = $repo->createNodeForResource($post, $user, $thread->getResourceNode());
3061
    $em->persist($resourceNode);
3062
    $repo->addResourceNodeToCourse(
3063
        $resourceNode,
3064
        ResourceLink::VISIBILITY_PUBLISHED,
3065
        $course,
3066
        $session,
3067
        null
3068
    );
3069
    $em->persist($post);
3070
    $em->flush();
3071
3072
    $postId = $post->getIid();
3073
    $thread->setThreadLastPost($postId);
3074
    $em->persist($thread);
3075
    $em->flush();
3076
3077
    $logInfo = [
3078
        'tool' => TOOL_FORUM,
3079
        'tool_id' => $values['forum_id'],
3080
        'tool_id_detail' => $thread->getIid(),
3081
        'action' => 'new-post',
3082
        'info' => $clean_post_title,
3083
    ];
3084
    Event::registerLog($logInfo);
3085
3086
    if ($postId) {
3087
        $post->setPostId($postId);
3088
        $em->persist($post);
3089
        $em->flush();
3090
    }
3091
3092
    // Update attached files
3093
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3094
        foreach ($_POST['file_ids'] as $key => $id) {
3095
            editAttachedFile(
3096
                [
3097
                    'comment' => $_POST['file_comments'][$key],
3098
                    'post_id' => $postId,
3099
                ],
3100
                $id
3101
            );
3102
        }
3103
    }
3104
3105
    // Now we have to update the thread table to fill the thread_last_post
3106
    // field (so that we know when the thread has been updated for the last time).
3107
    $sql = "UPDATE $table_threads
3108
            SET thread_last_post = '".Database::escape_string($postId)."'
3109
            WHERE
3110
                c_id = $course_id AND
3111
                thread_id='".Database::escape_string($thread->getIid())."'";
3112
    $result = Database::query($sql);
3113
    $message = get_lang('The new thread has been added');
3114
3115
    // Overwrite default message.
3116
    if ($forum->isModerated() &&
3117
        !api_is_allowed_to_edit(null, true)
3118
    ) {
3119
        $message = get_lang('Your message has to be approved before people can view it.');
3120
    }
3121
3122
    // Storing the attachments if any.
3123
    if ($has_attachment) {
3124
        // Try to add an extension to the file if it hasn't one.
3125
        $new_file_name = add_ext_on_mime(
3126
            stripslashes($_FILES['user_upload']['name']),
3127
            $_FILES['user_upload']['type']
3128
        );
3129
3130
        if (!filter_extension($new_file_name)) {
3131
            if ($showMessage) {
3132
                Display::addFlash(Display::return_message(
3133
                    get_lang('File upload failed: this file extension or file type is prohibited'),
3134
                    'error'
3135
                ));
3136
            }
3137
        } else {
3138
            if ($result) {
3139
                add_forum_attachment_file(
3140
                    isset($values['file_comment']) ? $values['file_comment'] : null,
3141
                    $postId
3142
                );
3143
            }
3144
        }
3145
    } else {
3146
        $message .= '<br />';
3147
    }
3148
3149
    if ($forum->getApprovalDirectPost() == '1' &&
3150
        !api_is_allowed_to_edit(null, true)
3151
    ) {
3152
        $message .= get_lang('Your message has to be approved before people can view it.').'<br />';
3153
        $message .= get_lang('You can now return to the').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
3154
            get_lang('Forum').'</a><br />';
3155
    } else {
3156
        $message .= get_lang('You can now return to the').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
3157
            get_lang('Forum').'</a><br />';
3158
        $message .= get_lang('You can now return to the').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&thread='.$thread->getIid().'">'.
3159
            get_lang('Message').'</a>';
3160
    }
3161
    $reply_info['new_post_id'] = $postId;
3162
    $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3163
3164
    if ($my_post_notification == 1) {
3165
        set_notification('thread', $thread->getIid(), true);
3166
    }
3167
3168
    send_notification_mails(
3169
        $forum,
3170
        $thread,
3171
        $reply_info,
3172
        $courseInfo['code']
3173
    );
3174
3175
    Session::erase('formelements');
3176
    Session::erase('origin');
3177
    Session::erase('breadcrumbs');
3178
    Session::erase('addedresource');
3179
    Session::erase('addedresourceid');
3180
3181
    if ($showMessage) {
3182
        Display::addFlash(Display::return_message($message, 'success', false));
3183
    }
3184
3185
    return $thread;
3186
}
3187
3188
/**
3189
 * This function displays the form that is used to add a post. This can be a new thread or a reply.
3190
 *
3191
     * @param array  $current_forum
3192
 * @param string $action        is the parameter that determines if we are
3193
 *                              2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
3194
 *                              3. replymessage: Replying to a message ($action =replymessage) => I-frame with the complete thread (if enabled)
3195
 *                              (I first thought to put and I-frame with the message only)
3196
 *                              4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread (if enabled).
3197
 *                              The message will be in the reply. (I first thought not to put an I-frame here)
3198
 * @param array  $form_values
3199
 * @param bool   $showPreview
3200
 *
3201
 * @return FormValidator
3202
 */
3203
function show_add_post_form(CForumForum $current_forum, CForumThread $thread, $action, $form_values = '', $showPreview = true)
3204
{
3205
    $_user = api_get_user_info();
3206
    $action = isset($action) ? Security::remove_XSS($action) : '';
3207
    $threadId = $thread->getIid();
3208
    $forumId = $current_forum->getIid();
3209
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
3210
    $giveRevision = isset($_GET['give_revision']) && $_GET['give_revision'] == 1;
3211
3212
    $url = api_get_self().'?'.http_build_query(
3213
        [
3214
            'action' => $action,
3215
            'forum' => $forumId,
3216
            'thread' => $threadId,
3217
            'post' => $my_post,
3218
        ]
3219
    ).'&'.api_get_cidreq();
3220
3221
    $form = new FormValidator(
3222
        'thread',
3223
        'post',
3224
        $url
3225
    );
3226
3227
    $form->setConstants(['forum' => '5']);
3228
3229
    // Setting the form elements.
3230
    $form->addElement('hidden', 'forum_id', $forumId);
3231
    $form->addElement('hidden', 'thread_id', $threadId);
3232
    $form->addElement('hidden', 'action', $action);
3233
3234
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
3235
    if ($current_forum->getAllowAnonymous() == 1 && !isset($_user['user_id'])) {
3236
        $form->addElement('text', 'poster_name', get_lang('Name'));
3237
        $form->applyFilter('poster_name', 'html_filter');
3238
    }
3239
3240
    $form->addElement('text', 'post_title', get_lang('Title'));
3241
    $form->addHtmlEditor(
3242
        'post_text',
3243
        get_lang('Text'),
3244
        true,
3245
        false,
3246
        api_is_allowed_to_edit(null, true) ? [
3247
            'ToolbarSet' => 'Forum',
3248
            'Width' => '100%',
3249
            'Height' => '300',
3250
        ] : [
3251
            'ToolbarSet' => 'ForumStudent',
3252
            'Width' => '100%',
3253
            'Height' => '300',
3254
            'UserStatus' => 'student',
3255
        ]
3256
    );
3257
    $form->addRule('post_text', get_lang('Required field'), 'required');
3258
3259
    if (in_array($action, ['replythread', 'replymessage', 'quote'])) {
3260
        $extraFields = new ExtraField('forum_post');
3261
        $extraFields->addElements(
3262
            $form,
3263
            null,
3264
            [], //exclude
3265
            false, // filter
3266
            false, // tag as select
3267
            ['ask_for_revision'], //show only fields
3268
            [], // order fields
3269
            [] // extra data);
3270
        );
3271
    }
3272
3273
    $iframe = null;
3274
    if ($showPreview) {
3275
        if ($action != 'newthread' && !empty($threadId)) {
3276
            $iframe = "<iframe style=\"border: 1px solid black\" src=\"iframe_thread.php?".api_get_cidreq(
3277
                )."&forum=".$forumId."&thread=".$threadId."#".$my_post."\" width=\"100%\"></iframe>";
3278
        }
3279
        if (!empty($iframe)) {
3280
            $form->addElement('label', get_lang('Thread'), $iframe);
3281
        }
3282
    }
3283
3284
    if (in_array($action, ['quote', 'replymessage'])) {
3285
        $form->addFile('user_upload[]', get_lang('Attachment'));
3286
        $form->addButton(
3287
            'add_attachment',
3288
            get_lang('Add attachment'),
3289
            'paperclip',
3290
            'default',
3291
            'default',
3292
            null,
3293
            ['id' => 'reply-add-attachment']
3294
        );
3295
    } else {
3296
        $form->addFile('user_upload', get_lang('Attachment'));
3297
    }
3298
3299
    if ($giveRevision) {
3300
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
3301
        $form->addHidden('give_revision', 1);
3302
        if ($hide === false) {
3303
            $extraField = new ExtraField('forum_post');
3304
            $extraField->addElements(
3305
                $form,
3306
                null,
3307
                [], //exclude
3308
                false, // filter
3309
                false, // tag as select
3310
                ['revision_language'], //show only fields
3311
                [], // order fields
3312
                [] // extra data
3313
            );
3314
        } else {
3315
            $form->addHidden('extra_revision_language', 1);
3316
        }
3317
    }
3318
3319
    // Setting the class and text of the form title and submit button.
3320
    if ($action === 'quote') {
3321
        $form->addButtonCreate(get_lang('Quote this message'), 'SubmitPost');
3322
    } elseif ($action === 'replythread') {
3323
        $form->addButtonCreate(get_lang('Reply to this thread'), 'SubmitPost');
3324
    } elseif ($action === 'replymessage') {
3325
        $form->addButtonCreate(get_lang('Reply to this message'), 'SubmitPost');
3326
    }
3327
3328
    $defaults['thread_peer_qualify'] = 0;
3329
    if (!empty($form_values)) {
3330
        $defaults['post_title'] = prepare4display($form_values['post_title']);
3331
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3332
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3333
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3334
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3335
    }
3336
3337
    // If we are quoting a message we have to retrieve the information of the post we are quoting so that
3338
    // we can add this as default to the textarea.
3339
    // We also need to put the parent_id of the post in a hidden form when
3340
    if (($action == 'quote' || $action == 'replymessage' || $giveRevision) && !empty($my_post)) {
3341
        // we are quoting or replying to a message (<> reply to a thread !!!)
3342
        $form->addHidden('post_parent_id', $my_post);
3343
3344
        // If we are replying or are quoting then we display a default title.
3345
        $values = get_post_information($my_post);
3346
        $posterInfo = api_get_user_info($values['poster_id']);
3347
        $posterName = '';
3348
        if ($posterInfo) {
3349
            $posterName = $posterInfo['complete_name'];
3350
        }
3351
        $defaults['post_title'] = get_lang('Re:').api_html_entity_decode($values['post_title'], ENT_QUOTES);
3352
        // When we are quoting a message then we have to put that message into the wysiwyg editor.
3353
        // Note: The style has to be hardcoded here because using class="quote" didn't work.
3354
        if ($action == 'quote') {
3355
            $defaults['post_text'] = '<div>&nbsp;</div>
3356
                <div style="margin: 5px;">
3357
                    <div style="font-size: 90%; font-style: italic;">'.
3358
                get_lang('Quoting').' '.$posterName.':</div>
3359
                        <div style="color: #006600; font-size: 90%;  font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.
3360
                prepare4display($values['post_text']).'
3361
                        </div>
3362
                    </div>
3363
                <div>&nbsp;</div>
3364
                <div>&nbsp;</div>
3365
            ';
3366
        }
3367
        if ($giveRevision) {
3368
            $defaults['post_text'] = prepare4display($values['post_text']);
3369
        }
3370
    }
3371
3372
    $form->setDefaults(isset($defaults) ? $defaults : []);
3373
3374
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3375
    $form->addRule('post_title', get_lang('Required field'), 'required');
3376
    if ($current_forum->getAllowAnonymous() == 1 && !isset($_user['user_id'])) {
3377
        $form->addRule(
3378
            'poster_name',
3379
            get_lang('Required field'),
3380
            'required'
3381
        );
3382
    }
3383
3384
    // Validation or display
3385
    if ($form->validate()) {
3386
        $check = Security::check_token('post');
3387
        if ($check) {
3388
            $values = $form->getSubmitValues();
3389
            if (isset($values['thread_qualify_gradebook']) &&
3390
                $values['thread_qualify_gradebook'] == '1' &&
3391
                empty($values['weight_calification'])
3392
            ) {
3393
                Display::addFlash(
3394
                    Display::return_message(
3395
                        get_lang('You must assign a score to this activity').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3396
                        'error',
3397
                        false
3398
                    )
3399
                );
3400
3401
                return false;
3402
            }
3403
3404
            $postId = 0;
3405
            $threadId = 0;
3406
3407
            switch ($action) {
3408
                case 'quote':
3409
                case 'replythread':
3410
                case 'replymessage':
3411
                    $postId = store_reply($current_forum, $thread, $values);
3412
                    break;
3413
            }
3414
3415
            if ($postId) {
3416
                $postInfo = get_post_information($postId);
3417
                if ($postInfo) {
3418
                    $threadId = $postInfo['thread_id'];
3419
                }
3420
3421
                if (isset($values['give_revision']) && $values['give_revision'] == 1) {
3422
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3423
                    $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
3424
3425
                    $params = [
3426
                        'item_id' => $postId,
3427
                        'extra_revision_language' => $revisionLanguage,
3428
                    ];
3429
3430
                    $extraFieldValues->saveFieldValues(
3431
                        $params,
3432
                        false,
3433
                        false,
3434
                        ['revision_language']
3435
                    );
3436
                }
3437
3438
                if (in_array($action, ['replythread', 'replymessage', 'quote'])) {
3439
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3440
                    $params = [
3441
                        'item_id' => $postId,
3442
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
3443
                    ];
3444
                    $extraFieldValues->saveFieldValues(
3445
                        $params,
3446
                        false,
3447
                        false,
3448
                        ['ask_for_revision']
3449
                    );
3450
                }
3451
            }
3452
3453
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3454
                [
3455
                    'forum' => $forumId,
3456
                    'thread' => $threadId,
3457
                ]
3458
            );
3459
3460
            Security::clear_token();
3461
            header('Location: '.$url);
3462
            exit;
3463
        }
3464
    } else {
3465
        $token = Security::get_token();
3466
        $form->addElement('hidden', 'sec_token');
3467
        $form->setConstants(['sec_token' => $token]);
3468
3469
        // Delete from $_SESSION forum attachment from other posts
3470
        // and keep only attachments for new post
3471
        clearAttachedFiles(FORUM_NEW_POST);
3472
        // Get forum attachment ajax table to add it to form
3473
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $current_forum->getIid());
3474
        $ajaxHtml = $attachmentAjaxTable;
3475
        $form->addElement('html', $ajaxHtml);
3476
3477
        return $form;
3478
    }
3479
}
3480
3481
function newThread(CForumForum $current_forum, $form_values = '', $showPreview = true)
3482
{
3483
    $_user = api_get_user_info();
3484
    $forumId = $current_forum->getIid();
3485
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
3486
    $giveRevision = isset($_GET['give_revision']) && $_GET['give_revision'] == 1;
3487
3488
    $url = api_get_self().'?'.http_build_query(
3489
            [
3490
                'action' => $action,
3491
                'forum' => $forumId,
3492
                'post' => $my_post,
3493
            ]
3494
        ).'&'.api_get_cidreq();
3495
3496
    $form = new FormValidator(
3497
        'thread',
3498
        'post',
3499
        $url
3500
    );
3501
3502
    // Setting the form elements.
3503
    $form->addElement('hidden', 'forum_id', $forumId);
3504
    $form->addElement('hidden', 'thread_id', 0);
3505
    $form->addElement('hidden', 'action', $action);
3506
3507
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
3508
    if ($current_forum->getAllowAnonymous() == 1 && !isset($_user['user_id'])) {
3509
        $form->addElement('text', 'poster_name', get_lang('Name'));
3510
        $form->applyFilter('poster_name', 'html_filter');
3511
    }
3512
3513
    $form->addElement('text', 'post_title', get_lang('Title'));
3514
    $form->addHtmlEditor(
3515
        'post_text',
3516
        get_lang('Text'),
3517
        true,
3518
        false,
3519
        api_is_allowed_to_edit(null, true) ? [
3520
            'ToolbarSet' => 'Forum',
3521
            'Width' => '100%',
3522
            'Height' => '300',
3523
        ] : [
3524
            'ToolbarSet' => 'ForumStudent',
3525
            'Width' => '100%',
3526
            'Height' => '300',
3527
            'UserStatus' => 'student',
3528
        ]
3529
    );
3530
    $form->addRule('post_text', get_lang('Required field'), 'required');
3531
3532
3533
    $extraFields = new ExtraField('forum_post');
3534
    $extraFields->addElements(
3535
        $form,
3536
        null,
3537
        [], //exclude
3538
        false, // filter
3539
        false, // tag as select
3540
        ['ask_for_revision'], //show only fields
3541
        [], // order fields
3542
        [] // extra data);
3543
    );
3544
3545
    if (Gradebook::is_active() &&
3546
        (api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor())
3547
    ) {
3548
        $form->addElement('advanced_settings', 'advanced_params', get_lang('Advanced settings'));
3549
        $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
3550
3551
        // Thread qualify
3552
        if (Gradebook::is_active()) {
3553
            //Loading gradebook select
3554
            GradebookUtils::load_gradebook_select_in_tool($form);
3555
            $form->addElement(
3556
                'checkbox',
3557
                'thread_qualify_gradebook',
3558
                '',
3559
                get_lang('Grade this thread'),
3560
                'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
3561
            );
3562
        } else {
3563
            $form->addElement('hidden', 'thread_qualify_gradebook', false);
3564
        }
3565
3566
        $form->addElement('html', '<div id="options_field" style="display:none">');
3567
        $form->addElement('text', 'numeric_calification', get_lang('Maximum score'));
3568
        $form->applyFilter('numeric_calification', 'html_filter');
3569
        $form->addElement('text', 'calification_notebook_title', get_lang('Column header in Competences Report'));
3570
        $form->applyFilter('calification_notebook_title', 'html_filter');
3571
3572
        $form->addElement(
3573
            'text',
3574
            'weight_calification',
3575
            get_lang('Weight in Report'),
3576
            ['value' => '0.00', 'onfocus' => "javascript: this.select();"]
3577
        );
3578
        $form->applyFilter('weight_calification', 'html_filter');
3579
3580
        $group = [];
3581
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
3582
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
3583
        $form->addGroup(
3584
            $group,
3585
            '',
3586
            [
3587
                get_lang('Thread scored by peers'),
3588
                get_lang('Thread scored by peersComment'),
3589
            ]
3590
        );
3591
        $form->addElement('html', '</div>');
3592
        $form->addElement('html', '</div>');
3593
    }
3594
3595
    Skill::addSkillsToForm($form, ITEM_TYPE_FORUM_THREAD, 0);
3596
    $form->addElement('checkbox', 'thread_sticky', '', get_lang('This is a sticky message (appears always on top and has a special sticky icon)'));
3597
3598
    $form->addFile('user_upload', get_lang('Attachment'));
3599
3600
    if ($giveRevision) {
3601
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
3602
        $form->addHidden('give_revision', 1);
3603
        if ($hide === false) {
3604
            $extraField = new ExtraField('forum_post');
3605
            $extraField->addElements(
3606
                $form,
3607
                null,
3608
                [], //exclude
3609
                false, // filter
3610
                false, // tag as select
3611
                ['revision_language'], //show only fields
3612
                [], // order fields
3613
                [] // extra data
3614
            );
3615
        } else {
3616
            $form->addHidden('extra_revision_language', 1);
3617
        }
3618
    }
3619
    $form->addButtonCreate(get_lang('Create thread'), 'SubmitPost');
3620
3621
    $defaults['thread_peer_qualify'] = 0;
3622
    if (!empty($form_values)) {
3623
        $defaults['post_title'] = prepare4display($form_values['post_title']);
3624
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3625
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3626
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3627
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3628
    }
3629
3630
    $form->setDefaults(isset($defaults) ? $defaults : []);
3631
3632
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3633
    $form->addRule('post_title', get_lang('Required field'), 'required');
3634
    if ($current_forum->getAllowAnonymous() == 1 && !isset($_user['user_id'])) {
3635
        $form->addRule(
3636
            'poster_name',
3637
            get_lang('Required field'),
3638
            'required'
3639
        );
3640
    }
3641
3642
    // Validation or display
3643
    if ($form->validate()) {
3644
        $check = Security::check_token('post');
3645
        if ($check) {
3646
            $values = $form->getSubmitValues();
3647
            if (isset($values['thread_qualify_gradebook']) &&
3648
                $values['thread_qualify_gradebook'] == '1' &&
3649
                empty($values['weight_calification'])
3650
            ) {
3651
                Display::addFlash(
3652
                    Display::return_message(
3653
                        get_lang('You must assign a score to this activity').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3654
                        'error',
3655
                        false
3656
                    )
3657
                );
3658
3659
                return false;
3660
            }
3661
3662
            $postId = 0;
3663
            $threadId = 0;
3664
3665
            $newThread = store_thread($current_forum, $values);
3666
            if ($newThread) {
3667
                Skill::saveSkills($form, ITEM_TYPE_FORUM_THREAD, $newThread->getIid());
3668
                $postId = $newThread->getThreadLastPost();
3669
3670
                if ($postId) {
3671
                    $postInfo = get_post_information($postId);
3672
                    if ($postInfo) {
3673
                        $threadId = $postInfo['thread_id'];
3674
                    }
3675
3676
                    if (isset($values['give_revision']) && $values['give_revision'] == 1) {
3677
                        $extraFieldValues = new ExtraFieldValue('forum_post');
3678
                        $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
3679
3680
                        $params = [
3681
                            'item_id' => $postId,
3682
                            'extra_revision_language' => $revisionLanguage,
3683
                        ];
3684
3685
                        $extraFieldValues->saveFieldValues(
3686
                            $params,
3687
                            false,
3688
                            false,
3689
                            ['revision_language']
3690
                        );
3691
                    }
3692
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3693
                    $params = [
3694
                        'item_id' => $postId,
3695
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
3696
                    ];
3697
                    $extraFieldValues->saveFieldValues(
3698
                        $params,
3699
                        false,
3700
                        false,
3701
                        ['ask_for_revision']
3702
                    );
3703
                }
3704
            }
3705
3706
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3707
                [
3708
                    'forum' => $forumId,
3709
                    'thread' => $threadId,
3710
                ]
3711
            );
3712
3713
            Security::clear_token();
3714
            header('Location: '.$url);
3715
            exit;
3716
        }
3717
    } else {
3718
        $token = Security::get_token();
3719
        $form->addElement('hidden', 'sec_token');
3720
        $form->setConstants(['sec_token' => $token]);
3721
3722
        // Delete from $_SESSION forum attachment from other posts
3723
        // and keep only attachments for new post
3724
        clearAttachedFiles(FORUM_NEW_POST);
3725
        // Get forum attachment ajax table to add it to form
3726
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $current_forum->getIid());
3727
        $ajaxHtml = $attachmentAjaxTable;
3728
        $form->addElement('html', $ajaxHtml);
3729
3730
        return $form;
3731
    }
3732
}
3733
3734
/**
3735
 * @param array $threadInfo
3736
 * @param int   $user_id
3737
 * @param int   $thread_id
3738
 * @param int   $thread_qualify
3739
 * @param int   $qualify_time
3740
 * @param int   $session_id
3741
 *
3742
 * @return array optional
3743
 *
3744
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3745
 *
3746
 * @version October 2008, dokeos  1.8.6
3747
 */
3748
function saveThreadScore(
3749
    $threadInfo,
3750
    $user_id,
3751
    $thread_id,
3752
    $thread_qualify = 0,
3753
    $qualify_time,
3754
    $session_id = 0
3755
) {
3756
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3757
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3758
3759
    $course_id = api_get_course_int_id();
3760
    $session_id = intval($session_id);
3761
    $currentUserId = api_get_user_id();
3762
3763
    if ($user_id == strval(intval($user_id)) &&
3764
        $thread_id == strval(intval($thread_id)) &&
3765
        $thread_qualify == strval(floatval($thread_qualify))
3766
    ) {
3767
        // Testing
3768
        $sql = "SELECT thread_qualify_max FROM $table_threads
3769
                WHERE c_id = $course_id AND thread_id=".$thread_id;
3770
        $res_string = Database::query($sql);
3771
        $row_string = Database::fetch_array($res_string);
3772
        if ($thread_qualify <= $row_string[0]) {
3773
            if ($threadInfo['thread_peer_qualify'] == 0) {
3774
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3775
                        WHERE
3776
                            c_id = $course_id AND
3777
                            user_id = $user_id AND
3778
                            thread_id = ".$thread_id;
3779
            } else {
3780
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3781
                        WHERE
3782
                            c_id = $course_id AND
3783
                            user_id = $user_id AND
3784
                            qualify_user_id = $currentUserId AND
3785
                            thread_id = ".$thread_id;
3786
            }
3787
3788
            $result = Database::query($sql);
3789
            $row = Database::fetch_array($result);
3790
3791
            if ($row[0] == 0) {
3792
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3793
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3794
                Database::query($sql);
3795
                $insertId = Database::insert_id();
3796
                if ($insertId) {
3797
                    $sql = "UPDATE $table_threads_qualify SET id = iid
3798
                            WHERE iid = $insertId";
3799
                    Database::query($sql);
3800
                }
3801
3802
                return 'insert';
3803
            } else {
3804
                saveThreadScoreHistory(
3805
                    '1',
3806
                    $course_id,
3807
                    $user_id,
3808
                    $thread_id
3809
                );
3810
3811
                // Update
3812
                $sql = "UPDATE $table_threads_qualify
3813
                        SET
3814
                            qualify = '".$thread_qualify."',
3815
                            qualify_time = '".$qualify_time."'
3816
                        WHERE
3817
                            c_id = $course_id AND
3818
                            user_id=".$user_id." AND
3819
                            thread_id=".$thread_id." AND
3820
                            qualify_user_id = $currentUserId
3821
                        ";
3822
                Database::query($sql);
3823
3824
                return 'update';
3825
            }
3826
        } else {
3827
            return null;
3828
        }
3829
    }
3830
}
3831
3832
/**
3833
 * This function shows qualify.
3834
 *
3835
 * @param string $option    contains the information of option to run
3836
 * @param int    $user_id   contains the information the current user id
3837
 * @param int    $thread_id contains the information the current thread id
3838
 *
3839
 * @return int qualify
3840
 *             <code> $option=1 obtained the qualification of the current thread</code>
3841
 *
3842
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3843
 *
3844
 * @version October 2008, dokeos  1.8.6
3845
 */
3846
function showQualify($option, $user_id, $thread_id)
3847
{
3848
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3849
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3850
3851
    $course_id = api_get_course_int_id();
3852
    $user_id = (int) $user_id;
3853
    $thread_id = (int) $thread_id;
3854
3855
    if (empty($user_id) || empty($thread_id)) {
3856
        return false;
3857
    }
3858
3859
    $sql = '';
3860
    switch ($option) {
3861
        case 1:
3862
            $sql = "SELECT qualify FROM $table_threads_qualify
3863
                    WHERE
3864
                        c_id = $course_id AND
3865
                        user_id=".$user_id." AND
3866
                        thread_id=".$thread_id;
3867
            break;
3868
        case 2:
3869
            $sql = "SELECT thread_qualify_max FROM $table_threads
3870
                    WHERE c_id = $course_id AND thread_id=".$thread_id;
3871
            break;
3872
    }
3873
3874
    if (!empty($sql)) {
3875
        $rs = Database::query($sql);
3876
        $row = Database::fetch_array($rs);
3877
3878
        return $row[0];
3879
    }
3880
3881
    return [];
3882
}
3883
3884
/**
3885
 * This function gets qualify historical.
3886
 *
3887
 * @param int  $user_id   contains the information the current user id
3888
 * @param int  $thread_id contains the information the current thread id
3889
 * @param bool $opt       contains the information of option to run
3890
 *
3891
 * @return array
3892
 *
3893
 * @author Christian Fasanando <[email protected]>,
3894
 * @author Isaac Flores <[email protected]>,
3895
 *
3896
 * @version October 2008, dokeos  1.8.6
3897
 */
3898
function getThreadScoreHistory($user_id, $thread_id, $opt)
3899
{
3900
    $user_id = (int) $user_id;
3901
    $thread_id = (int) $thread_id;
3902
3903
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3904
    $course_id = api_get_course_int_id();
3905
3906
    if ($opt == 'false') {
3907
        $sql = "SELECT * FROM $table_threads_qualify_log
3908
                WHERE
3909
                    c_id = $course_id AND
3910
                    thread_id='".$thread_id."' AND
3911
                    user_id='".$user_id."'
3912
                ORDER BY qualify_time";
3913
    } else {
3914
        $sql = "SELECT * FROM $table_threads_qualify_log
3915
                WHERE
3916
                    c_id = $course_id AND
3917
                    thread_id='".$thread_id."' AND
3918
                    user_id='".$user_id."'
3919
                ORDER BY qualify_time DESC";
3920
    }
3921
    $rs = Database::query($sql);
3922
    $log = [];
3923
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3924
        $log[] = $row;
3925
    }
3926
3927
    return $log;
3928
}
3929
3930
/**
3931
 * This function stores qualify historical.
3932
 *
3933
 * @param bool contains the information of option to run
3934
 * @param string contains the information the current course id
3935
 * @param int contains the information the current forum id
3936
 * @param int contains the information the current user id
3937
 * @param int contains the information the current thread id
3938
 * @param int contains the information the current qualify
3939
 * @param string $option
3940
 * @param int    $course_id
3941
 * @param int    $user_id
3942
 * @param int    $thread_id
3943
 *
3944
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3945
 *
3946
 * @version October 2008, dokeos  1.8.6
3947
 */
3948
function saveThreadScoreHistory(
3949
    $option,
3950
    $course_id,
3951
    $user_id,
3952
    $thread_id
3953
) {
3954
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3955
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3956
3957
    $course_id = intval($course_id);
3958
    $qualify_user_id = api_get_user_id();
3959
3960
    if ($user_id == strval(intval($user_id)) &&
3961
        $thread_id == strval(intval($thread_id)) && $option == 1
3962
    ) {
3963
        // Extract information of thread_qualify.
3964
        $sql = "SELECT qualify, qualify_time
3965
                FROM $table_threads_qualify
3966
                WHERE
3967
                    c_id = $course_id AND
3968
                    user_id = ".$user_id." AND
3969
                    thread_id = ".$thread_id." AND
3970
                    qualify_user_id = $qualify_user_id
3971
                ";
3972
        $rs = Database::query($sql);
3973
        $row = Database::fetch_array($rs);
3974
3975
        // Insert thread_historical.
3976
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3977
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3978
        Database::query($sql);
3979
3980
        $insertId = Database::insert_id();
3981
        if ($insertId) {
3982
            $sql = "UPDATE $table_threads_qualify_log SET id = iid
3983
                    WHERE iid = $insertId";
3984
            Database::query($sql);
3985
        }
3986
    }
3987
}
3988
3989
/**
3990
 * This function shows current thread qualify .
3991
 *
3992
 * @param int $threadId
3993
 * @param int $sessionId
3994
 * @param int $userId
3995
 *
3996
 * @return array or null if is empty
3997
 *
3998
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3999
 *
4000
 * @version December 2008, dokeos  1.8.6
4001
 */
4002
function current_qualify_of_thread($threadId, $sessionId, $userId)
4003
{
4004
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
4005
4006
    $course_id = api_get_course_int_id();
4007
    $currentUserId = api_get_user_id();
4008
    $sessionId = intval($sessionId);
4009
    $threadId = intval($threadId);
4010
4011
    $sql = "SELECT qualify FROM $table_threads_qualify
4012
            WHERE
4013
                c_id = $course_id AND
4014
                thread_id = $threadId AND
4015
                session_id = $sessionId AND
4016
                qualify_user_id = $currentUserId AND
4017
                user_id = $userId
4018
            ";
4019
    $res = Database::query($sql);
4020
    $row = Database::fetch_array($res, 'ASSOC');
4021
4022
    return $row['qualify'];
4023
}
4024
4025
/**
4026
 * This function stores a reply in the forum_post table.
4027
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date).
4028
 *
4029
 * @param CForumForum  $current_forum
4030
 * @param CForumThread $thread
4031
 * @param array        $values
4032
 * @param int          $courseId Optional
4033
 * @param int          $userId   Optional
4034
 *
4035
 * @return int post id
4036
 */
4037
function store_reply(CForumForum $current_forum, CForumThread $thread, $values, $courseId = 0, $userId = 0)
4038
{
4039
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
4040
    $_course = api_get_course_info_by_id($courseId);
4041
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4042
    $post_date = api_get_utc_datetime();
4043
    $userId = $userId ?: api_get_user_id();
4044
4045
    if ($current_forum->getAllowAnonymous() == 1) {
4046
        if (api_is_anonymous() && empty($userId)) {
4047
            $userId = api_get_anonymous_id();
4048
        }
4049
    }
4050
4051
    if (empty($userId)) {
4052
        return false;
4053
    }
4054
4055
    $visible = 1;
4056
    if ($current_forum->getApprovalDirectPost() == '1' &&
4057
        !api_is_allowed_to_edit(null, true)
4058
    ) {
4059
        $visible = 0;
4060
    }
4061
4062
    $upload_ok = 1;
4063
    $new_post_id = 0;
4064
4065
    if ($upload_ok) {
4066
        $post = new CForumPost();
4067
        $post
4068
            ->setCId($courseId)
4069
            ->setPostTitle($values['post_title'])
4070
            ->setPostText(isset($values['post_text']) ? ($values['post_text']) : null)
4071
            ->setThread($thread)
4072
            ->setForumId($current_forum->getIid())
4073
            ->setPosterId($userId)
4074
            ->setPostNotification(isset($values['post_notification']) ? $values['post_notification'] : null)
4075
            ->setPostParentId(isset($values['post_parent_id']) ? $values['post_parent_id'] : null)
4076
            ->setVisible($visible)
4077
            ->setPostDate(api_get_utc_datetime(null, false, true))
4078
        ;
4079
4080
        $repo = Container::getForumPostRepository();
4081
4082
        $user = api_get_user_entity(api_get_user_id());
4083
        $course = api_get_course_entity($courseId);
4084
        $session = api_get_session_entity();
4085
4086
        $em = $repo->getEntityManager();
4087
        //$em->persist($thread);
4088
        $resourceNode = $repo->createNodeForResource($post, $user, $thread->getResourceNode());
4089
        $repo->addResourceNodeToCourse(
4090
            $resourceNode,
4091
            ResourceLink::VISIBILITY_PUBLISHED,
4092
            $course,
4093
            $session,
4094
            null
4095
        );
4096
        $em->flush();
4097
4098
        $new_post_id = $post->getIid();
4099
4100
        if ($new_post_id) {
4101
            $sql = "UPDATE $table_posts SET post_id = iid WHERE iid = $new_post_id";
4102
            Database::query($sql);
4103
4104
            $values['new_post_id'] = $new_post_id;
4105
            $message = get_lang('The reply has been added');
4106
4107
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
4108
                foreach ($_POST['file_ids'] as $key => $id) {
4109
                    editAttachedFile(
4110
                        [
4111
                            'comment' => $_POST['file_comments'][$key],
4112
                            'post_id' => $new_post_id,
4113
                        ],
4114
                        $id
4115
                    );
4116
                }
4117
            }
4118
4119
            // Update the thread.
4120
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
4121
4122
            // Update the forum.
4123
            /*api_item_property_update(
4124
                $_course,
4125
                TOOL_FORUM,
4126
                $values['forum_id'],
4127
                'NewMessageInForum',
4128
                $userId
4129
            );
4130
4131
            // Insert post
4132
            api_item_property_update(
4133
                $_course,
4134
                TOOL_FORUM_POST,
4135
                $new_post_id,
4136
                'NewPost',
4137
                $userId
4138
            );*/
4139
4140
            if ($current_forum->getApprovalDirectPost() == '1' &&
4141
                !api_is_allowed_to_edit(null, true)
4142
            ) {
4143
                $message .= '<br />'.get_lang('Your message has to be approved before people can view it.').'<br />';
4144
            }
4145
4146
            if ($current_forum->isModerated() &&
4147
                !api_is_allowed_to_edit(null, true)
4148
            ) {
4149
                $message .= '<br />'.get_lang('Your message has to be approved before people can view it.').'<br />';
4150
            }
4151
4152
            // Setting the notification correctly.
4153
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
4154
            if ($my_post_notification == 1) {
4155
                set_notification('thread', $values['thread_id'], true);
4156
            }
4157
4158
            send_notification_mails(
4159
                $current_forum,
4160
                $thread,
4161
                $values
4162
            );
4163
            add_forum_attachment_file('', $new_post_id);
4164
4165
            $logInfo = [
4166
                'tool' => TOOL_FORUM,
4167
                'tool_id' => $values['forum_id'],
4168
                'tool_id_detail' => $values['thread_id'],
4169
                'action' => 'new-post',
4170
                'action_details' => $values['action'],
4171
                'info' => $values['post_title'],
4172
            ];
4173
            Event::registerLog($logInfo);
4174
        }
4175
4176
        Session::erase('formelements');
4177
        Session::erase('origin');
4178
        Session::erase('breadcrumbs');
4179
        Session::erase('addedresource');
4180
        Session::erase('addedresourceid');
4181
4182
        Display::addFlash(Display::return_message($message, 'confirmation', false));
4183
    } else {
4184
        Display::addFlash(
4185
            Display::return_message(
4186
                get_lang('No file was uploaded.').' '.get_lang('Please select a file before pressing the upload button.'),
4187
                'error'
4188
            )
4189
        );
4190
    }
4191
4192
    return $new_post_id;
4193
}
4194
4195
/**
4196
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
4197
 *
4198
 * @param array contains all the information about the current post
4199
 * @param array contains all the information about the current thread
4200
 * @param array contains all info about the current forum (to check if attachments are allowed)
4201
 * @param array contains the default values to fill the form
4202
 *
4203
 * @author Patrick Cool <[email protected]>, Ghent University
4204
 *
4205
 * @version february 2006, dokeos 1.8
4206
 */
4207
function show_edit_post_form(
4208
    $current_post,
4209
    $current_thread,
4210
    $current_forum,
4211
    $form_values = '',
4212
    $id_attach = 0
4213
) {
4214
    // Initialize the object.
4215
    $form = new FormValidator(
4216
        'edit_post',
4217
        'post',
4218
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.intval($_GET['post'])
4219
    );
4220
    $form->addElement('header', get_lang('Edit a post'));
4221
    // Setting the form elements.
4222
    $form->addElement('hidden', 'post_id', $current_post['post_id']);
4223
    $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
4224
    $form->addElement('hidden', 'id_attach', $id_attach);
4225
4226
    if (empty($current_post['post_parent_id'])) {
4227
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
4228
    }
4229
4230
    $form->addElement('text', 'post_title', get_lang('Title'));
4231
    $form->applyFilter('post_title', 'html_filter');
4232
    $form->addElement(
4233
        'html_editor',
4234
        'post_text',
4235
        get_lang('Text'),
4236
        null,
4237
        api_is_allowed_to_edit(null, true) ? [
4238
            'ToolbarSet' => 'Forum',
4239
            'Width' => '100%',
4240
            'Height' => '400',
4241
        ] : [
4242
            'ToolbarSet' => 'ForumStudent',
4243
            'Width' => '100%',
4244
            'Height' => '400',
4245
            'UserStatus' => 'student',
4246
        ]
4247
    );
4248
    $form->addRule('post_text', get_lang('Required field'), 'required');
4249
4250
    $extraFields = new ExtraField('forum_post');
4251
    $extraFields->addElements($form, $current_post['post_id']);
4252
4253
    $form->addButtonAdvancedSettings('advanced_params');
4254
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
4255
4256
    if ($current_forum['moderated'] && api_is_allowed_to_edit(null, true)) {
4257
        $group = [];
4258
        $group[] = $form->createElement(
4259
            'radio',
4260
            'status',
4261
            null,
4262
            get_lang('Validated'),
4263
            1
4264
        );
4265
        $group[] = $form->createElement(
4266
            'radio',
4267
            'status',
4268
            null,
4269
            get_lang('Waiting for moderation'),
4270
            2
4271
        );
4272
        $group[] = $form->createElement(
4273
            'radio',
4274
            'status',
4275
            null,
4276
            get_lang('Rejected'),
4277
            3
4278
        );
4279
        $form->addGroup($group, 'status', get_lang('Status'));
4280
    }
4281
4282
    $defaults['status']['status'] = isset($current_post['status']) && !empty($current_post['status']) ? $current_post['status'] : 2;
4283
    $form->addElement(
4284
        'checkbox',
4285
        'post_notification',
4286
        '',
4287
        get_lang('Notify me by e-mail when somebody replies').' ('.$current_post['email'].')'
4288
    );
4289
4290
    if (api_is_allowed_to_edit(null, true) &&
4291
        empty($current_post['post_parent_id'])
4292
    ) {
4293
        // The sticky checkbox only appears when it is the first post of a thread.
4294
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('This is a sticky message (appears always on top and has a special sticky icon)'));
4295
        if ($current_thread['thread_sticky'] == 1) {
4296
            $defaults['thread_sticky'] = true;
4297
        }
4298
    }
4299
4300
    $form->addElement('html', '</div>');
4301
4302
    $form->addFile('user_upload[]', get_lang('Attachment'));
4303
    $form->addButton(
4304
        'add_attachment',
4305
        get_lang('Add attachment'),
4306
        'paperclip',
4307
        'default',
4308
        'default',
4309
        null,
4310
        ['id' => 'reply-add-attachment']
4311
    );
4312
4313
    $form->addButtonUpdate(get_lang('Edit'), 'SubmitPost');
4314
4315
    // Setting the default values for the form elements.
4316
    $defaults['post_title'] = $current_post['post_title'];
4317
    $defaults['post_text'] = $current_post['post_text'];
4318
4319
    if ($current_post['post_notification'] == 1) {
4320
        $defaults['post_notification'] = true;
4321
    }
4322
4323
    if (!empty($form_values)) {
4324
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
4325
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
4326
    }
4327
4328
    $form->setDefaults($defaults);
4329
4330
    // The course admin can make a thread sticky (=appears with special icon and always on top).
4331
4332
    $form->addRule('post_title', get_lang('Required field'), 'required');
4333
4334
    // Validation or display
4335
    if ($form->validate()) {
4336
        $values = $form->exportValues();
4337
4338
        $values['item_id'] = $current_post['post_id'];
4339
        $extraFieldValues = new ExtraFieldValue('forum_post');
4340
        $extraFieldValues->saveFieldValues($values);
4341
4342
        store_edit_post($current_forum, $values);
4343
    } else {
4344
        // Delete from $_SESSION forum attachment from other posts
4345
        clearAttachedFiles($current_post['post_id']);
4346
        // Get forum attachment ajax table to add it to form
4347
        $fileData = getAttachmentsAjaxTable($current_post['post_id'], $current_forum['forum_id']);
4348
        $form->addElement('html', $fileData);
4349
        $form->display();
4350
    }
4351
}
4352
4353
/**
4354
 * This function stores the edit of a post in the forum_post table.
4355
 *
4356
 * @param array
4357
 *
4358
 * @author Patrick Cool <[email protected]>, Ghent University
4359
 *
4360
 * @version february 2006, dokeos 1.8
4361
 */
4362
function store_edit_post($forumInfo, $values)
4363
{
4364
    $logInfo = [
4365
        'tool' => TOOL_FORUM,
4366
        'tool_id' => $_GET['forum'],
4367
        'tool_id_detail' => $values['thread_id'],
4368
        'action' => 'edit-post',
4369
        'action_details' => 'post',
4370
        'info' => $values['post_title'],
4371
    ];
4372
    Event::registerLog($logInfo);
4373
4374
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
4375
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4376
    $course_id = api_get_course_int_id();
4377
4378
    //check if this post is the first of the thread
4379
    // First we check if the change affects the thread and if so we commit
4380
    // the changes (sticky and post_title=thread_title are relevant).
4381
4382
    $posts = getPosts($forumInfo, $values['thread_id']);
4383
    $first_post = null;
4384
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
4385
        $first_post = $posts[0];
4386
    }
4387
4388
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
4389
        // Simple edit
4390
        $params = [
4391
            'thread_title' => $values['post_title'],
4392
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
4393
        ];
4394
        $where = ['c_id = ? AND thread_id = ?' => [$course_id, $values['thread_id']]];
4395
        Database::update($threadTable, $params, $where);
4396
    }
4397
4398
    $status = '';
4399
    $updateStatus = false;
4400
    if ($forumInfo['moderated']) {
4401
        if (api_is_allowed_to_edit(null, true)) {
4402
            $status = $values['status']['status'];
4403
            $updateStatus = true;
4404
        } else {
4405
            $status = CForumPost::STATUS_WAITING_MODERATION;
4406
            $updateStatus = true;
4407
        }
4408
    }
4409
4410
    // Update the post_title and the post_text.
4411
    $params = [
4412
        'post_title' => $values['post_title'],
4413
        'post_text' => $values['post_text'],
4414
        'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : '',
4415
    ];
4416
4417
    if ($updateStatus) {
4418
        $params['status'] = $status;
4419
    }
4420
4421
    $where = ['c_id = ? AND post_id = ?' => [$course_id, $values['post_id']]];
4422
    Database::update($table_posts, $params, $where);
4423
4424
    // Update attached files
4425
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
4426
        foreach ($_POST['file_ids'] as $key => $id) {
4427
            editAttachedFile(
4428
                [
4429
                    'comment' => $_POST['file_comments'][$key],
4430
                    'post_id' => $values['post_id'],
4431
                ],
4432
                $id
4433
            );
4434
        }
4435
    }
4436
4437
    if (!empty($values['remove_attach'])) {
4438
        delete_attachment($values['post_id']);
4439
    }
4440
4441
    if (empty($values['id_attach'])) {
4442
        add_forum_attachment_file(
4443
            isset($values['file_comment']) ? $values['file_comment'] : null,
4444
            $values['post_id']
4445
        );
4446
    } else {
4447
        edit_forum_attachment_file(
4448
            isset($values['file_comment']) ? $values['file_comment'] : null,
4449
            $values['post_id'],
4450
            $values['id_attach']
4451
        );
4452
    }
4453
4454
    $message = get_lang('The post has been modified').'<br />';
4455
    $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 />';
4456
    $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>';
4457
4458
    Session::erase('formelements');
4459
    Session::erase('origin');
4460
    Session::erase('breadcrumbs');
4461
    Session::erase('addedresource');
4462
    Session::erase('addedresourceid');
4463
4464
    echo Display::return_message($message, 'confirmation', false);
4465
}
4466
4467
/**
4468
 * This function displays the firstname and lastname of the user as a link to the user tool.
4469
 *
4470
 * @param string names
4471
 * @ in_title : title tootip
4472
 *
4473
 * @return string HTML
4474
 *
4475
 * @author Patrick Cool <[email protected]>, Ghent University
4476
 *
4477
 * @version february 2006, dokeos 1.8
4478
 */
4479
function display_user_link($user_id, $name, $origin = '', $in_title = '')
4480
{
4481
    if ($user_id != 0) {
4482
        $userInfo = api_get_user_info($user_id);
4483
4484
        return '<a href="'.$userInfo['profile_url'].'">'.Security::remove_XSS($userInfo['complete_name']).'</a>';
4485
    } else {
4486
        return $name.' ('.get_lang('Anonymous').')';
4487
    }
4488
}
4489
4490
/**
4491
 * This function displays the user image from the profile, with a link to the user's details.
4492
 *
4493
 * @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...
4494
 * @param   string  User's name
4495
 * @param   string  the origin where the forum is called (example : learnpath)
4496
 *
4497
 * @return string An HTML with the anchor and the image of the user
4498
 *
4499
 * @author Julio Montoya <[email protected]>
4500
 */
4501
function display_user_image($user_id, $name, $origin = '')
4502
{
4503
    $userInfo = api_get_user_info($user_id);
4504
    $link = '<a href="'.(!empty($origin) ? '#' : $userInfo['profile_url']).'" '.(!empty($origin) ? 'target="_self"' : '').'>';
4505
4506
    if ($user_id != 0) {
4507
        return $link.'<img src="'.$userInfo['avatar'].'"  alt="'.$name.'"  title="'.$name.'" /></a>';
4508
    } else {
4509
        return $link.Display::return_icon('unknown.jpg', $name).'</a>';
4510
    }
4511
}
4512
4513
/**
4514
 * The thread view counter gets increased every time someone looks at the thread.
4515
 *
4516
 * @param int
4517
 *
4518
 * @author Patrick Cool <[email protected]>, Ghent University
4519
 *
4520
 * @version february 2006, dokeos 1.8
4521
 */
4522
function increase_thread_view($thread_id)
4523
{
4524
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4525
    $course_id = api_get_course_int_id();
4526
4527
    $sql = "UPDATE $table_threads
4528
            SET thread_views = thread_views + 1
4529
            WHERE
4530
                c_id = $course_id AND
4531
                thread_id = '".intval($thread_id)."'";
4532
    Database::query($sql);
4533
}
4534
4535
/**
4536
 * The relies counter gets increased every time somebody replies to the thread.
4537
 *
4538
 * @author Patrick Cool <[email protected]>, Ghent University
4539
 *
4540
 * @version february 2006, dokeos 1.8
4541
 *
4542
 * @param int    $threadId
4543
 * @param string $lastPostId
4544
 * @param string $post_date
4545
 */
4546
function updateThreadInfo($threadId, $lastPostId, $post_date)
4547
{
4548
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4549
    $course_id = api_get_course_int_id();
4550
    $sql = "UPDATE $table_threads SET
4551
            thread_replies = thread_replies+1,
4552
            thread_last_post = '".Database::escape_string($lastPostId)."',
4553
            thread_date = '".Database::escape_string($post_date)."'
4554
            WHERE
4555
                c_id = $course_id AND
4556
                thread_id='".Database::escape_string($threadId)."'"; // this needs to be cleaned first
4557
    Database::query($sql);
4558
}
4559
4560
/**
4561
 * This function is used to find all the information about what's new in the forum tool.
4562
 *
4563
 * @author Patrick Cool <[email protected]>, Ghent University
4564
 *
4565
 * @version february 2006, dokeos 1.8
4566
 */
4567
function get_whats_new()
4568
{
4569
    $userId = api_get_user_id();
4570
    $course_id = api_get_course_int_id();
4571
4572
    if (empty($course_id) || empty($userId)) {
4573
        return false;
4574
    }
4575
4576
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4577
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
4578
4579
    $tool = TOOL_FORUM;
4580
    $lastForumAccess = Session::read('last_forum_access');
4581
4582
    if (!$lastForumAccess) {
4583
        $sql = "SELECT * FROM $tracking_last_tool_access
4584
                WHERE
4585
                    access_user_id = $userId AND
4586
                    c_id = $course_id AND
4587
                    access_tool = '".Database::escape_string($tool)."'";
4588
        $result = Database::query($sql);
4589
        $row = Database::fetch_array($result);
4590
        if ($row) {
4591
            Session::write('last_forum_access', $row['access_date']);
4592
            $lastForumAccess = $row['access_date'];
4593
        }
4594
    }
4595
4596
    $whatsNew = Session::read('whatsnew_post_info');
4597
4598
    if (!$whatsNew) {
4599
        if ($lastForumAccess != '') {
4600
            $postInfo = [];
4601
            $sql = "SELECT * FROM $table_posts
4602
                    WHERE
4603
                        c_id = $course_id AND
4604
                        visible = 1 AND
4605
                        post_date > '".Database::escape_string($lastForumAccess)."'";
4606
            $result = Database::query($sql);
4607
            while ($row = Database::fetch_array($result)) {
4608
                $postInfo[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
4609
            }
4610
            Session::write('whatsnew_post_info', $postInfo);
4611
        }
4612
    }
4613
}
4614
4615
/**
4616
 * This function approves a post = change.
4617
 *
4618
 * @param int    $post_id the id of the post that will be deleted
4619
 * @param string $action  make the post visible or invisible
4620
 *
4621
 * @return string language variable
4622
 *
4623
 * @author Patrick Cool <[email protected]>, Ghent University
4624
 *
4625
 * @version february 2006, dokeos 1.8
4626
 */
4627
function approve_post($post_id, $action)
4628
{
4629
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4630
    $course_id = api_get_course_int_id();
4631
4632
    if ($action == 'invisible') {
4633
        $visibility_value = 0;
4634
    }
4635
4636
    if ($action == 'visible') {
4637
        $visibility_value = 1;
4638
        handle_mail_cue('post', $post_id);
4639
    }
4640
4641
    $sql = "UPDATE $table_posts SET
4642
            visible='".Database::escape_string($visibility_value)."'
4643
            WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
4644
    $return = Database::query($sql);
4645
4646
    if ($return) {
4647
        return 'PostThe visibility has been changed.';
4648
    }
4649
}
4650
4651
/**
4652
 * This function retrieves all the unapproved messages for a given forum
4653
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this).
4654
 *
4655
 * @param $forum_id the forum where we want to know the unapproved messages of
4656
 *
4657
 * @return array returns
4658
 *
4659
 * @author Patrick Cool <[email protected]>, Ghent University
4660
 *
4661
 * @version february 2006, dokeos 1.8
4662
 */
4663
function get_unaproved_messages($forum_id)
4664
{
4665
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4666
    $course_id = api_get_course_int_id();
4667
4668
    $return_array = [];
4669
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
4670
            WHERE
4671
                c_id = $course_id AND
4672
                forum_id='".Database::escape_string($forum_id)."' AND
4673
                visible='0' ";
4674
    $result = Database::query($sql);
4675
    while ($row = Database::fetch_array($result)) {
4676
        $return_array[] = $row['thread_id'];
4677
    }
4678
4679
    return $return_array;
4680
}
4681
4682
/**
4683
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
4684
 * was added to a given thread.
4685
 *
4686
 * @param array reply information
4687
 */
4688
function send_notification_mails(CForumForum $forum, CForumThread $thread, $reply_info)
4689
{
4690
    $_course = api_get_course_info();
4691
    $courseEntity = $_course['entity'];
4692
    $sessionId = api_get_session_id();
4693
    $sessionEntity = api_get_session_entity($sessionId);
4694
4695
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4696
4697
    // First we need to check if
4698
    // 1. the forum category is visible
4699
    // 2. the forum is visible
4700
    // 3. the thread is visible
4701
    // 4. the reply is visible (=when there is)
4702
4703
    $current_forum_category = null;
4704
    if ($forum->getForumCategory()) {
4705
        $current_forum_category = $forum->getForumCategory();
4706
    }
4707
4708
    $send_mails = false;
4709
    if ($thread->isVisible($courseEntity, $sessionEntity) &&
4710
        $forum->isVisible($courseEntity, $sessionEntity) &&
4711
        ($current_forum_category && $forum->getForumCategory()->isVisible($courseEntity, $sessionEntity)) &&
4712
        $forum->getApprovalDirectPost() != '1'
4713
    ) {
4714
        $send_mails = true;
4715
    }
4716
4717
    // The forum category, the forum, the thread and the reply are visible to the user
4718
    if ($send_mails && !empty($forum)) {
4719
        $postId = isset($reply_info['new_post_id']) ? $reply_info['new_post_id'] : 0;
4720
        send_notifications($forum, $thread, $postId);
4721
    } else {
4722
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
4723
        if ($forum) {
4724
            $sql = "SELECT * FROM $table_notification
4725
                    WHERE
4726
                        c_id = ".api_get_course_int_id()." AND
4727
                        (
4728
                            forum_id = '".$forum->getIid()."' OR
4729
                            thread_id = '".$thread->getIid()."'
4730
                        ) ";
4731
            $result = Database::query($sql);
4732
            $user_id = api_get_user_id();
4733
            while ($row = Database::fetch_array($result)) {
4734
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
4735
                        VALUES (".api_get_course_int_id().", '".$thread->getIid()."', '".intval($reply_info['new_post_id'])."', '$user_id' )";
4736
                Database::query($sql);
4737
            }
4738
        }
4739
    }
4740
}
4741
4742
/**
4743
 * This function is called whenever something is made visible because there might
4744
 * be new posts and the user might have indicated that (s)he wanted to be
4745
 * informed about the new posts by mail.
4746
 *
4747
 * @param string $content Content type (post, thread, forum, forum_category)
4748
 * @param int    $id      Item DB ID of the corresponding content type
4749
 *
4750
 * @return string language variable
4751
 *
4752
 * @author Patrick Cool <[email protected]>, Ghent University
4753
 *
4754
 * @version february 2006, dokeos 1.8
4755
 */
4756
function handle_mail_cue($content, $id)
4757
{
4758
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4759
    $table_forums = Database::get_course_table(TABLE_FORUM);
4760
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4761
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4762
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4763
4764
    $course_id = api_get_course_int_id();
4765
    $id = (int) $id;
4766
4767
    /* If the post is made visible we only have to send mails to the people
4768
     who indicated that they wanted to be informed for that thread.*/
4769
    if ($content == 'post') {
4770
        // Getting the information about the post (need the thread_id).
4771
        $post_info = get_post_information($id);
4772
        $thread_id = (int) $post_info['thread_id'];
4773
4774
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4775
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
4776
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4777
                WHERE
4778
                    posts.c_id = $course_id AND
4779
                    mailcue.c_id = $course_id AND
4780
                    posts.thread_id = $thread_id AND
4781
                    posts.post_notification = '1' AND
4782
                    mailcue.thread_id = $thread_id AND
4783
                    users.user_id = posts.poster_id AND
4784
                    users.active = 1
4785
                GROUP BY users.email";
4786
4787
        $result = Database::query($sql);
4788
        while ($row = Database::fetch_array($result)) {
4789
            $forumInfo = get_forum_information($post_info['forum_id']);
4790
            send_mail($row, $forumInfo, get_thread_information($post_info['forum_id'], $post_info['thread_id']), $post_info);
4791
        }
4792
    } elseif ($content == 'thread') {
4793
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4794
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email, posts.forum_id
4795
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4796
                WHERE
4797
                    posts.c_id = $course_id AND
4798
                    mailcue.c_id = $course_id AND
4799
                    posts.thread_id = $id AND
4800
                    posts.post_notification = '1' AND
4801
                    mailcue.thread_id = $id AND
4802
                    users.user_id = posts.poster_id AND
4803
                    users.active = 1
4804
                GROUP BY users.email";
4805
        $result = Database::query($sql);
4806
        while ($row = Database::fetch_array($result)) {
4807
            $forumInfo = get_forum_information($row['forum_id']);
4808
            send_mail($row, $forumInfo, get_thread_information($row['forum_id'], $id));
4809
        }
4810
4811
        // Deleting the relevant entries from the mailcue.
4812
        $sql = "DELETE FROM $table_mailcue
4813
                WHERE c_id = $course_id AND thread_id = $id";
4814
        Database::query($sql);
4815
    } elseif ($content == 'forum') {
4816
        $sql = "SELECT thread_id FROM $table_threads
4817
                WHERE c_id = $course_id AND forum_id = $id";
4818
        $result = Database::query($sql);
4819
        while ($row = Database::fetch_array($result)) {
4820
            handle_mail_cue('thread', $row['thread_id']);
4821
        }
4822
    } elseif ($content == 'forum_category') {
4823
        $sql = "SELECT forum_id FROM $table_forums
4824
                WHERE c_id = $course_id AND forum_category = $id";
4825
        $result = Database::query($sql);
4826
        while ($row = Database::fetch_array($result)) {
4827
            handle_mail_cue('forum', $row['forum_id']);
4828
        }
4829
    } else {
4830
        return get_lang('Error');
4831
    }
4832
}
4833
4834
/**
4835
 * This function sends the mails for the mail notification.
4836
 *
4837
 * @param array        $userInfo
4838
 * @param CForumForum  $forum
4839
 * @param CForumThread $thread
4840
 * @param array
4841
 *
4842
 */
4843
function send_mail($userInfo, CForumForum $forum, CForumThread $thread, $postInfo = [])
4844
{
4845
    if (empty($userInfo) || empty($forum) || empty($thread)) {
4846
        return false;
4847
    }
4848
4849
    $_course = api_get_course_info();
4850
    $user_id = api_get_user_id();
4851
    $forumId = $forum->getIid();
4852
    $threadId = $thread->getIid();
4853
4854
    $thread_link = api_get_path(WEB_CODE_PATH).
4855
        'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$threadId;
4856
4857
    $email_body = get_lang('Dear').' '.api_get_person_name($userInfo['firstname'], $userInfo['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4858
    $email_body .= get_lang('New Post in the forum').': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4859
4860
    $courseId = api_get_configuration_value('global_forums_course_id');
4861
    $subject = get_lang('New Post in the forum').' - '.$_course['official_code'].': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4862
4863
    $courseInfoTitle = get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4864
    if (!empty($courseId) && $_course['real_id'] == $courseId) {
4865
        $subject = get_lang('New Post in the forum').': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4866
        $courseInfoTitle = " <br />\n";
4867
    }
4868
    $email_body .= $courseInfoTitle;
4869
4870
    if (!empty($postInfo) && isset($postInfo['post_text'])) {
4871
        $text = cut(strip_tags($postInfo['post_text']), 100);
4872
        if (!empty($text)) {
4873
            $email_body .= get_lang('Message').": <br />\n ";
4874
            $email_body .= $text;
4875
            $email_body .= "<br /><br />\n";
4876
        }
4877
    }
4878
4879
    $email_body .= get_lang('You stated that you wanted to be informed by e-mail whenever somebody replies on the thread')."<br />\n";
4880
4881
    if (!empty($thread_link)) {
4882
        $email_body .= get_lang('The thread can be found here')." : <br /><a href=\"".$thread_link."\">".$thread_link."</a>\n";
4883
    }
4884
4885
    if ($userInfo['user_id'] != $user_id) {
4886
        MessageManager::send_message(
4887
            $userInfo['user_id'],
4888
            $subject,
4889
            $email_body,
4890
            [],
4891
            [],
4892
            null,
4893
            null,
4894
            null,
4895
            null,
4896
            $user_id
4897
        );
4898
    }
4899
}
4900
4901
/**
4902
 * This function displays the form for moving a thread to a different (already existing) forum.
4903
 *
4904
 * @author Patrick Cool <[email protected]>, Ghent University
4905
 *
4906
 * @version february 2006, dokeos 1.8
4907
 */
4908
function move_thread_form()
4909
{
4910
    $form = new FormValidator(
4911
        'movepost',
4912
        'post',
4913
        api_get_self().'?forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4914
    );
4915
    // The header for the form
4916
    $form->addElement('header', get_lang('Move Thread'));
4917
    // Invisible form: the thread_id
4918
    $form->addElement('hidden', 'thread_id', intval($_GET['thread']));
4919
    // the fora
4920
    $forum_categories = get_forum_categories();
4921
    $forums = get_forums();
4922
4923
    $htmlcontent = '<div class="row">
4924
        <div class="label">
4925
            <span class="form_required">*</span>'.get_lang('Move to').'
4926
        </div>
4927
        <div class="formw">';
4928
    $htmlcontent .= '<select name="forum">';
4929
    foreach ($forum_categories as $key => $category) {
4930
        $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
4931
        foreach ($forums as $key => $forum) {
4932
            if (isset($forum['forum_category'])) {
4933
                if ($forum['forum_category'] == $category['cat_id']) {
4934
                    $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
4935
                }
4936
            }
4937
        }
4938
        $htmlcontent .= '</optgroup>';
4939
    }
4940
    $htmlcontent .= "</select>";
4941
    $htmlcontent .= '   </div>
4942
                    </div>';
4943
4944
    $form->addElement('html', $htmlcontent);
4945
4946
    // The OK button
4947
    $form->addButtonSave(get_lang('Move Thread'), 'SubmitForum');
4948
4949
    // Validation or display
4950
    if ($form->validate()) {
4951
        $values = $form->exportValues();
4952
        if (isset($_POST['forum'])) {
4953
            store_move_thread($values);
4954
        }
4955
    } else {
4956
        $form->display();
4957
    }
4958
}
4959
4960
/**
4961
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4962
 *
4963
 * @author Patrick Cool <[email protected]>, Ghent University
4964
 *
4965
 * @version february 2006, dokeos 1.8
4966
 */
4967
function move_post_form()
4968
{
4969
    $form = new FormValidator(
4970
        'movepost',
4971
        'post',
4972
        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'])
4973
    );
4974
    // The header for the form
4975
    $form->addElement('header', '', get_lang('Move post'));
4976
4977
    // Invisible form: the post_id
4978
    $form->addElement('hidden', 'post_id', intval($_GET['post']));
4979
4980
    // Dropdown list: Threads of this forum
4981
    $threads = get_threads($_GET['forum']);
4982
    //my_print_r($threads);
4983
    $threads_list[0] = get_lang('A new thread');
4984
    foreach ($threads as $key => $value) {
4985
        $threads_list[$value['thread_id']] = $value['thread_title'];
4986
    }
4987
    $form->addElement('select', 'thread', get_lang('Move toThread'), $threads_list);
4988
    $form->applyFilter('thread', 'html_filter');
4989
4990
    // The OK button
4991
    $form->addButtonSave(get_lang('Move post'), 'submit');
4992
4993
    // Setting the rules
4994
    $form->addRule('thread', get_lang('Required field'), 'required');
4995
4996
    // Validation or display
4997
    if ($form->validate()) {
4998
        $values = $form->exportValues();
4999
        store_move_post($values);
5000
    } else {
5001
        $form->display();
5002
    }
5003
}
5004
5005
/**
5006
 * @param array
5007
 *
5008
 * @return string HTML language variable
5009
 *
5010
 * @author Patrick Cool <[email protected]>, Ghent University
5011
 *
5012
 * @version february 2006, dokeos 1.8
5013
 */
5014
function store_move_post($values)
5015
{
5016
    $_course = api_get_course_info();
5017
    $course_id = api_get_course_int_id();
5018
5019
    $table_forums = Database::get_course_table(TABLE_FORUM);
5020
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5021
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5022
5023
    if ($values['thread'] == '0') {
5024
        $current_post = get_post_information($values['post_id']);
5025
5026
        // Storing a new thread.
5027
        $params = [
5028
            'c_id' => $course_id,
5029
            'thread_title' => $current_post['post_title'],
5030
            'forum_id' => $current_post['forum_id'],
5031
            'thread_poster_id' => $current_post['poster_id'],
5032
            'thread_poster_name' => $current_post['poster_name'],
5033
            'thread_last_post' => $values['post_id'],
5034
            'thread_date' => $current_post['post_date'],
5035
        ];
5036
5037
        $new_thread_id = Database::insert($table_threads, $params);
5038
5039
        api_item_property_update(
5040
            $_course,
5041
            TOOL_FORUM_THREAD,
5042
            $new_thread_id,
5043
            'visible',
5044
            $current_post['poster_id']
5045
        );
5046
5047
        // Moving the post to the newly created thread.
5048
        $sql = "UPDATE $table_posts SET thread_id='".intval($new_thread_id)."', post_parent_id = NULL
5049
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
5050
        Database::query($sql);
5051
5052
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
5053
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
5054
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
5055
        Database::query($sql);
5056
5057
        // Updating updating the number of threads in the forum.
5058
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
5059
                WHERE c_id = $course_id AND forum_id='".intval($current_post['forum_id'])."'";
5060
        Database::query($sql);
5061
5062
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
5063
        $sql = "SELECT * FROM $table_posts
5064
                WHERE c_id = $course_id AND thread_id='".intval($current_post['thread_id'])."'
5065
                ORDER BY post_id DESC";
5066
        $result = Database::query($sql);
5067
        $row = Database::fetch_array($result);
5068
        $sql = "UPDATE $table_threads SET
5069
                    thread_last_post='".$row['post_id']."',
5070
                    thread_replies=thread_replies-1
5071
                WHERE
5072
                    c_id = $course_id AND
5073
                    thread_id='".intval($current_post['thread_id'])."'";
5074
        Database::query($sql);
5075
    } else {
5076
        // Moving to the chosen thread.
5077
        $sql = "SELECT thread_id FROM ".$table_posts."
5078
                WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
5079
        $result = Database::query($sql);
5080
        $row = Database::fetch_array($result);
5081
5082
        $original_thread_id = $row['thread_id'];
5083
5084
        $sql = "SELECT thread_last_post FROM ".$table_threads."
5085
                WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
5086
5087
        $result = Database::query($sql);
5088
        $row = Database::fetch_array($result);
5089
        $thread_is_last_post = $row['thread_last_post'];
5090
        // If is this thread, update the thread_last_post with the last one.
5091
5092
        if ($thread_is_last_post == $values['post_id']) {
5093
            $sql = "SELECT post_id FROM ".$table_posts."
5094
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."'
5095
                    ORDER BY post_date DESC LIMIT 1";
5096
            $result = Database::query($sql);
5097
5098
            $row = Database::fetch_array($result);
5099
            $thread_new_last_post = $row['post_id'];
5100
5101
            $sql = "UPDATE ".$table_threads." SET thread_last_post = '".$thread_new_last_post."'
5102
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
5103
            Database::query($sql);
5104
        }
5105
5106
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
5107
                WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
5108
        Database::query($sql);
5109
5110
        // moving to the chosen thread
5111
        $sql = "UPDATE $table_posts SET thread_id='".intval($_POST['thread'])."', post_parent_id = NULL
5112
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
5113
        Database::query($sql);
5114
5115
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
5116
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
5117
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
5118
        Database::query($sql);
5119
5120
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
5121
                WHERE c_id = $course_id AND thread_id='".intval($_POST['thread'])."'";
5122
        Database::query($sql);
5123
    }
5124
5125
    return get_lang('Thread moved');
5126
}
5127
5128
/**
5129
 * @param array
5130
 *
5131
 * @return string HTML language variable
5132
 *
5133
 * @author Patrick Cool <[email protected]>, Ghent University
5134
 *
5135
 * @version february 2006, dokeos 1.8
5136
 */
5137
function store_move_thread($values)
5138
{
5139
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5140
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5141
5142
    $courseId = api_get_course_int_id();
5143
    $sessionId = api_get_session_id();
5144
5145
    $forumId = intval($_POST['forum']);
5146
    $threadId = intval($_POST['thread_id']);
5147
    $forumInfo = get_forums($forumId);
5148
5149
    // Change the thread table: Setting the forum_id to the new forum.
5150
    $sql = "UPDATE $table_threads SET forum_id = $forumId
5151
            WHERE c_id = $courseId AND thread_id = $threadId";
5152
    Database::query($sql);
5153
5154
    // Changing all the posts of the thread: setting the forum_id to the new forum.
5155
    $sql = "UPDATE $table_posts SET forum_id = $forumId
5156
            WHERE c_id = $courseId AND thread_id= $threadId";
5157
    Database::query($sql);
5158
    // Fix group id, if forum is moved to a different group
5159
    if (!empty($forumInfo['to_group_id'])) {
5160
        $groupId = $forumInfo['to_group_id'];
5161
        $item = api_get_item_property_info(
5162
            $courseId,
5163
            TABLE_FORUM_THREAD,
5164
            $threadId,
5165
            $sessionId,
5166
            $groupId
5167
        );
5168
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
5169
        $sessionCondition = api_get_session_condition($sessionId);
5170
5171
        if (!empty($item)) {
5172
            if ($item['to_group_id'] != $groupId) {
5173
                $sql = "UPDATE $table
5174
                    SET to_group_id = $groupId
5175
                    WHERE
5176
                      tool = '".TABLE_FORUM_THREAD."' AND
5177
                      c_id = $courseId AND
5178
                      ref = ".$item['ref']."
5179
                      $sessionCondition
5180
                ";
5181
                Database::query($sql);
5182
            }
5183
        } else {
5184
            $sql = "UPDATE $table
5185
                    SET to_group_id = $groupId
5186
                    WHERE
5187
                      tool = '".TABLE_FORUM_THREAD."' AND
5188
                      c_id = $courseId AND
5189
                      ref = ".$threadId."
5190
                      $sessionCondition
5191
            ";
5192
            Database::query($sql);
5193
        }
5194
    }
5195
5196
    return get_lang('Thread moved');
5197
}
5198
5199
/**
5200
 * Prepares a string for displaying by highlighting the search results inside, if any.
5201
 *
5202
 * @param string $input the input string
5203
 *
5204
 * @return string the same string with highlighted hits inside
5205
 *
5206
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
5207
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
5208
 */
5209
function prepare4display($input)
5210
{
5211
    static $highlightcolors = ['yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33'];
5212
    static $search;
5213
5214
    if (!isset($search)) {
5215
        if (isset($_POST['search_term'])) {
5216
            $search = $_POST['search_term']; // No html at all.
5217
        } elseif (isset($_GET['search'])) {
5218
            $search = $_GET['search'];
5219
        } else {
5220
            $search = '';
5221
        }
5222
    }
5223
5224
    if (!empty($search)) {
5225
        if (strstr($search, '+')) {
5226
            $search_terms = explode('+', $search);
5227
        } else {
5228
            $search_terms[] = trim($search);
5229
        }
5230
        $counter = 0;
5231
        foreach ($search_terms as $key => $search_term) {
5232
            $input = api_preg_replace(
5233
                '/'.preg_quote(trim($search_term), '/').'/i',
5234
                '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
5235
                $input
5236
            );
5237
            $counter++;
5238
        }
5239
    }
5240
5241
    // TODO: Security should be implemented outside this function.
5242
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles
5243
    // (see comments of Security::remove_XSS() method to learn about other levels).
5244
5245
    return Security::remove_XSS($input, STUDENT, true);
5246
}
5247
5248
/**
5249
 * Display the search form for the forum and display the search results.
5250
 *
5251
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5252
 *
5253
 * @version march 2008, dokeos 1.8.5
5254
 */
5255
function forum_search()
5256
{
5257
    $form = new FormValidator(
5258
        'forumsearch',
5259
        'post',
5260
        'forumsearch.php?'.api_get_cidreq()
5261
    );
5262
5263
    // Setting the form elements.
5264
    $form->addElement('header', '', get_lang('Search in the Forum'));
5265
    $form->addElement('text', 'search_term', get_lang('Search term'), ['autofocus']);
5266
    $form->applyFilter('search_term', 'html_filter');
5267
    $form->addElement('static', 'search_information', '', get_lang('Search in the ForumInformation'));
5268
    $form->addButtonSearch(get_lang('Search'));
5269
5270
    // Setting the rules.
5271
    $form->addRule('search_term', get_lang('Required field'), 'required');
5272
    $form->addRule('search_term', get_lang('Too short'), 'minlength', 3);
5273
5274
    // Validation or display.
5275
    if ($form->validate()) {
5276
        $values = $form->exportValues();
5277
        $form->setDefaults($values);
5278
        $form->display();
5279
        // Display the search results.
5280
        display_forum_search_results(stripslashes($values['search_term']));
5281
    } else {
5282
        $form->display();
5283
    }
5284
}
5285
5286
/**
5287
 * Display the search results.
5288
 *
5289
 * @param string
5290
 * @param string $search_term
5291
 *
5292
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5293
 *
5294
 * @version march 2008, dokeos 1.8.5
5295
 */
5296
function display_forum_search_results($search_term)
5297
{
5298
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5299
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5300
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5301
    $session_id = api_get_session_id();
5302
    $course_id = api_get_course_int_id();
5303
5304
    // Defining the search strings as an array.
5305
    if (strstr($search_term, '+')) {
5306
        $search_terms = explode('+', $search_term);
5307
    } else {
5308
        $search_terms[] = $search_term;
5309
    }
5310
5311
    // Search restriction.
5312
    foreach ($search_terms as $value) {
5313
        $search_restriction[] = "
5314
        (
5315
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR
5316
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%'
5317
        )";
5318
    }
5319
5320
    $sessionCondition = api_get_session_condition(
5321
        $session_id,
5322
        true,
5323
        false,
5324
        'item_property.session_id'
5325
    );
5326
5327
    $sql = "SELECT posts.*
5328
            FROM $table_posts posts
5329
            INNER JOIN $table_threads threads
5330
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5331
            INNER JOIN $table_item_property item_property
5332
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
5333
            WHERE
5334
                posts.c_id = $course_id AND
5335
                item_property.c_id = $course_id AND
5336
                item_property.visibility = 1
5337
                $sessionCondition AND
5338
                posts.visible = 1 AND
5339
                item_property.tool = '".TOOL_FORUM_THREAD."' AND
5340
                ".implode(' AND ', $search_restriction)."
5341
            GROUP BY posts.post_id";
5342
5343
    // Getting all the information of the forum categories.
5344
    $forum_categories_list = get_forum_categories();
5345
5346
    // Getting all the information of the forums.
5347
    $forum_list = get_forums();
5348
5349
    $result = Database::query($sql);
5350
    $search_results = [];
5351
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5352
        $forumId = $row['forum_id'];
5353
        $forumData = get_forums($forumId);
5354
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
5355
        $display_result = false;
5356
        /*
5357
          We only show it when
5358
          1. forum category is visible
5359
          2. forum is visible
5360
          3. thread is visible (to do)
5361
          4. post is visible
5362
         */
5363
        if (!api_is_allowed_to_edit(null, true)) {
5364
            if (!empty($category)) {
5365
                if ($category['visibility'] == '1' && $forumData['visibility'] == '1') {
5366
                    $display_result = true;
5367
                }
5368
            } else {
5369
                if ($forumData['visible'] == '1') {
5370
                    $display_result = true;
5371
                }
5372
            }
5373
        } else {
5374
            $display_result = true;
5375
        }
5376
5377
        if ($display_result) {
5378
            $categoryName = !empty($category) ? $category['cat_title'] : '';
5379
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
5380
                prepare4display($categoryName).'</a> &gt; ';
5381
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
5382
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
5383
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
5384
                prepare4display($row['post_title']).'</a>';
5385
            $search_results_item .= '<br />';
5386
            if (api_strlen($row['post_title']) > 200) {
5387
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
5388
            } else {
5389
                $search_results_item .= prepare4display($row['post_title']);
5390
            }
5391
            $search_results_item .= '</li>';
5392
            $search_results[] = $search_results_item;
5393
        }
5394
    }
5395
    echo '<legend>'.count($search_results).' '.get_lang('Search in the ForumResults').'</legend>';
5396
    echo '<ol>';
5397
    if ($search_results) {
5398
        echo implode($search_results);
5399
    }
5400
    echo '</ol>';
5401
}
5402
5403
/**
5404
 * Return the link to the forum search page.
5405
 *
5406
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5407
 *
5408
 * @version April 2008, dokeos 1.8.5
5409
 */
5410
function search_link()
5411
{
5412
    $return = '';
5413
    $origin = api_get_origin();
5414
    if ($origin != 'learnpath') {
5415
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
5416
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
5417
5418
        if (!empty($_GET['search'])) {
5419
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
5420
            $url = api_get_self().'?';
5421
            $url_parameter = [];
5422
            foreach ($_GET as $key => $value) {
5423
                if ($key != 'search') {
5424
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
5425
                }
5426
            }
5427
            $url = $url.implode('&', $url_parameter);
5428
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('Clean search results')).'</a>';
5429
        }
5430
    }
5431
5432
    return $return;
5433
}
5434
5435
/**
5436
 * This function adds an attachment file into a forum.
5437
 *
5438
 * @param string $file_comment a comment about file
5439
 * @param int    $last_id      from forum_post table
5440
 *
5441
 * @return false|null
5442
 */
5443
function add_forum_attachment_file($file_comment, $last_id)
5444
{
5445
    $_course = api_get_course_info();
5446
    $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5447
5448
    if (empty($_FILES['user_upload'])) {
5449
        return false;
5450
    }
5451
5452
    $filesData = [];
5453
5454
    if (!is_array($_FILES['user_upload']['name'])) {
5455
        $filesData[] = $_FILES['user_upload'];
5456
    } else {
5457
        $fileCount = count($_FILES['user_upload']['name']);
5458
        $fileKeys = array_keys($_FILES['user_upload']);
5459
        for ($i = 0; $i < $fileCount; $i++) {
5460
            foreach ($fileKeys as $key) {
5461
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5462
            }
5463
        }
5464
    }
5465
5466
    foreach ($filesData as $attachment) {
5467
        if (empty($attachment['name'])) {
5468
            continue;
5469
        }
5470
5471
        $upload_ok = process_uploaded_file($attachment);
5472
5473
        if (!$upload_ok) {
5474
            continue;
5475
        }
5476
5477
        $course_dir = $_course['path'].'/upload/forum';
5478
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5479
        $updir = $sys_course_path.$course_dir;
5480
5481
        // Try to add an extension to the file if it hasn't one.
5482
        $new_file_name = add_ext_on_mime(
5483
            stripslashes($attachment['name']),
5484
            $attachment['type']
5485
        );
5486
        // User's file name
5487
        $file_name = $attachment['name'];
5488
5489
        if (!filter_extension($new_file_name)) {
5490
            Display::addFlash(
5491
                Display::return_message(
5492
                    get_lang('File upload failed: this file extension or file type is prohibited'),
5493
                    'error'
5494
                )
5495
            );
5496
5497
            return;
5498
        }
5499
5500
        $new_file_name = uniqid('');
5501
        $new_path = $updir.'/'.$new_file_name;
5502
        $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5503
        $safe_file_comment = Database::escape_string($file_comment);
5504
        $safe_file_name = Database::escape_string($file_name);
5505
        $safe_new_file_name = Database::escape_string($new_file_name);
5506
        $last_id = intval($last_id);
5507
        // Storing the attachments if any.
5508
        if (!$result) {
5509
            return;
5510
        }
5511
5512
        $last_id_file = Database::insert(
5513
            $agenda_forum_attachment,
5514
            [
5515
                'c_id' => api_get_course_int_id(),
5516
                'filename' => $safe_file_name,
5517
                'comment' => $safe_file_comment,
5518
                'path' => $safe_new_file_name,
5519
                'post_id' => $last_id,
5520
                'size' => intval($attachment['size']),
5521
            ]
5522
        );
5523
5524
        api_item_property_update(
5525
            $_course,
5526
            TOOL_FORUM_ATTACH,
5527
            $last_id_file,
5528
            'ForumAttachmentAdded',
5529
            api_get_user_id()
5530
        );
5531
    }
5532
}
5533
5534
/**
5535
 * This function edits an attachment file into a forum.
5536
 *
5537
 * @param string $file_comment a comment about file
5538
 * @param int    $post_id
5539
 * @param int    $id_attach    attachment file Id
5540
 */
5541
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
5542
{
5543
    $_course = api_get_course_info();
5544
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5545
    $course_id = api_get_course_int_id();
5546
5547
    $filesData = [];
5548
5549
    if (!is_array($_FILES['user_upload']['name'])) {
5550
        $filesData[] = $_FILES['user_upload'];
5551
    } else {
5552
        $fileCount = count($_FILES['user_upload']['name']);
5553
        $fileKeys = array_keys($_FILES['user_upload']);
5554
5555
        for ($i = 0; $i < $fileCount; $i++) {
5556
            foreach ($fileKeys as $key) {
5557
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
5558
            }
5559
        }
5560
    }
5561
5562
    foreach ($filesData as $attachment) {
5563
        if (empty($attachment['name'])) {
5564
            continue;
5565
        }
5566
5567
        $upload_ok = process_uploaded_file($attachment);
5568
5569
        if (!$upload_ok) {
5570
            continue;
5571
        }
5572
5573
        $course_dir = $_course['path'].'/upload/forum';
5574
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
5575
        $updir = $sys_course_path.$course_dir;
5576
5577
        // Try to add an extension to the file if it hasn't one.
5578
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
5579
        // User's file name
5580
        $file_name = $attachment['name'];
5581
5582
        if (!filter_extension($new_file_name)) {
5583
            Display::addFlash(
5584
                Display::return_message(
5585
                    get_lang('File upload failed: this file extension or file type is prohibited'),
5586
                    'error'
5587
                )
5588
            );
5589
        } else {
5590
            $new_file_name = uniqid('');
5591
            $new_path = $updir.'/'.$new_file_name;
5592
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
5593
            $safe_file_comment = Database::escape_string($file_comment);
5594
            $safe_file_name = Database::escape_string($file_name);
5595
            $safe_new_file_name = Database::escape_string($new_file_name);
5596
            $safe_post_id = (int) $post_id;
5597
            $safe_id_attach = (int) $id_attach;
5598
            // Storing the attachments if any.
5599
            if ($result) {
5600
                $sql = "UPDATE $table_forum_attachment
5601
                        SET
5602
                            filename = '$safe_file_name',
5603
                            comment = '$safe_file_comment',
5604
                            path = '$safe_new_file_name',
5605
                            post_id = '$safe_post_id',
5606
                            size ='".$attachment['size']."'
5607
                        WHERE c_id = $course_id AND id = '$safe_id_attach'";
5608
                Database::query($sql);
5609
                api_item_property_update(
5610
                    $_course,
5611
                    TOOL_FORUM_ATTACH,
5612
                    $safe_id_attach,
5613
                    'ForumAttachmentUpdated',
5614
                    api_get_user_id()
5615
                );
5616
            }
5617
        }
5618
    }
5619
}
5620
5621
/**
5622
 * Show a list with all the attachments according to the post's id.
5623
 *
5624
 * @param int $postId
5625
 *
5626
 * @return array with the post info
5627
 *
5628
 * @author Julio Montoya
5629
 *
5630
 * @version avril 2008, dokeos 1.8.5
5631
 */
5632
function get_attachment($postId)
5633
{
5634
    $table = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5635
    $course_id = api_get_course_int_id();
5636
    $row = [];
5637
    $postId = (int) $postId;
5638
5639
    if (empty($postId)) {
5640
        return [];
5641
    }
5642
5643
    $sql = "SELECT iid, path, filename, comment
5644
            FROM $table
5645
            WHERE c_id = $course_id AND post_id = $postId";
5646
    $result = Database::query($sql);
5647
    if (Database::num_rows($result) != 0) {
5648
        $row = Database::fetch_array($result);
5649
    }
5650
5651
    return $row;
5652
}
5653
5654
/**
5655
 * @param int $postId
5656
 *
5657
 * @return array
5658
 */
5659
function getAllAttachment($postId)
5660
{
5661
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5662
    $courseId = api_get_course_int_id();
5663
    $postId = (int) $postId;
5664
5665
    if (empty($postId)) {
5666
        return [];
5667
    }
5668
5669
    $columns = ['iid', 'path', 'filename', 'comment'];
5670
    $conditions = [
5671
        'where' => [
5672
            'c_id = ? AND post_id = ?' => [$courseId, $postId],
5673
        ],
5674
    ];
5675
    $array = Database::select(
5676
        $columns,
5677
        $forumAttachmentTable,
5678
        $conditions,
5679
        'all',
5680
        'ASSOC'
5681
    );
5682
5683
    return $array;
5684
}
5685
5686
/**
5687
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional).
5688
 *
5689
 * @param int $post_id
5690
 * @param int $id_attach
5691
 *
5692
 * @return int
5693
 *
5694
 * @author Julio Montoya
5695
 *
5696
 * @version october 2014, chamilo 1.9.8
5697
 */
5698
function delete_attachment($post_id, $id_attach = 0)
5699
{
5700
    $_course = api_get_course_info();
5701
5702
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5703
    $course_id = api_get_course_int_id();
5704
5705
    $cond = (!empty($id_attach)) ? " iid = ".(int) $id_attach."" : " post_id = ".(int) $post_id."";
5706
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
5707
    $res = Database::query($sql);
5708
    $row = Database::fetch_array($res);
5709
5710
    $course_dir = $_course['path'].'/upload/forum';
5711
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
5712
    $updir = $sys_course_path.$course_dir;
5713
    $my_path = isset($row['path']) ? $row['path'] : null;
5714
    $file = $updir.'/'.$my_path;
5715
    if (Security::check_abs_path($file, $updir)) {
5716
        @unlink($file);
5717
    }
5718
5719
    // Delete from forum_attachment table.
5720
    $sql = "DELETE FROM $forum_table_attachment
5721
            WHERE c_id = $course_id AND $cond ";
5722
    $result = Database::query($sql);
5723
    if ($result !== false) {
5724
        $affectedRows = Database::affected_rows($result);
5725
    } else {
5726
        $affectedRows = 0;
5727
    }
5728
5729
    // Update item_property.
5730
    api_item_property_update(
5731
        $_course,
5732
        TOOL_FORUM_ATTACH,
5733
        $id_attach,
5734
        'ForumAttachmentDelete',
5735
        api_get_user_id()
5736
    );
5737
5738
    if (!empty($result) && !empty($id_attach)) {
5739
        Display::addFlash(Display::return_message(get_lang('The attached file has been deleted'), 'confirmation'));
5740
    }
5741
5742
    return $affectedRows;
5743
}
5744
5745
/**
5746
 * This function gets all the forum information of the all the forum of the group.
5747
 *
5748
 * @param array $groupInfo the id of the group we need the fora of (see forum.forum_of_group)
5749
 *
5750
 * @return array
5751
 *
5752
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
5753
 */
5754
function get_forums_of_group($groupInfo)
5755
{
5756
    $table_forums = Database::get_course_table(TABLE_FORUM);
5757
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5758
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5759
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5760
    $course_id = api_get_course_int_id();
5761
    $groupId = (int) $groupInfo['id'];
5762
5763
    // Student
5764
    // Select all the forum information of all forums (that are visible to students).
5765
    $sql = "SELECT * FROM $table_forums forum
5766
            INNER JOIN $table_item_property item_properties
5767
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5768
            WHERE
5769
                forum.forum_of_group = $groupId AND
5770
                forum.c_id = $course_id AND
5771
                item_properties.c_id = $course_id AND
5772
                item_properties.visibility = 1 AND
5773
                item_properties.tool = '".TOOL_FORUM."'
5774
            ORDER BY forum.forum_order ASC";
5775
5776
    // Select the number of threads of the forums (only the threads that are visible).
5777
    $sql2 = "SELECT
5778
                count(thread_id) AS number_of_threads,
5779
                threads.forum_id
5780
            FROM $table_threads threads
5781
            INNER JOIN $table_item_property item_properties
5782
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5783
            WHERE
5784
                threads.c_id = $course_id AND
5785
                item_properties.c_id = $course_id AND
5786
                item_properties.visibility = 1 AND
5787
                item_properties.tool='".TOOL_FORUM_THREAD."'
5788
            GROUP BY threads.forum_id";
5789
5790
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
5791
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
5792
            FROM $table_posts posts
5793
            INNER JOIN $table_threads threads
5794
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5795
            INNER JOIN $table_item_property item_properties
5796
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5797
            WHERE
5798
                posts.visible=1 AND
5799
                posts.c_id = $course_id AND
5800
                item_properties.c_id = $course_id AND
5801
                threads.c_id = $course_id AND
5802
                item_properties.visibility = 1 AND
5803
                item_properties.tool='".TOOL_FORUM_THREAD."'
5804
            GROUP BY threads.forum_id";
5805
5806
    // Course Admin
5807
    if (api_is_allowed_to_edit()) {
5808
        // Select all the forum information of all forums (that are not deleted).
5809
        $sql = "SELECT *
5810
                FROM $table_forums forum
5811
                INNER JOIN $table_item_property item_properties
5812
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5813
                WHERE
5814
                    forum.forum_of_group = $groupId AND
5815
                    forum.c_id = $course_id AND
5816
                    item_properties.c_id = $course_id AND
5817
                    item_properties.visibility <> 2 AND
5818
                    item_properties.tool = '".TOOL_FORUM."'
5819
                ORDER BY forum_order ASC";
5820
5821
        // Select the number of threads of the forums (only the threads that are not deleted).
5822
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
5823
                 FROM $table_threads threads
5824
                 INNER JOIN $table_item_property item_properties
5825
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
5826
                 WHERE
5827
                    threads.c_id = $course_id AND
5828
                    item_properties.c_id = $course_id AND
5829
                    item_properties.visibility <> 2 AND
5830
                    item_properties.tool='".TOOL_FORUM_THREAD."'
5831
                GROUP BY threads.forum_id";
5832
        // Select the number of posts of the forum.
5833
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
5834
                FROM $table_posts
5835
                WHERE c_id = $course_id
5836
                GROUP BY forum_id";
5837
    }
5838
5839
    // Handling all the forum information.
5840
    $result = Database::query($sql);
5841
    $forum_list = [];
5842
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5843
        $forum_list[$row['forum_id']] = $row;
5844
    }
5845
5846
    // Handling the thread count information.
5847
    $result2 = Database::query($sql2);
5848
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5849
        if (is_array($forum_list)) {
5850
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5851
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5852
            }
5853
        }
5854
    }
5855
5856
    // Handling the post count information.
5857
    $result3 = Database::query($sql3);
5858
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5859
        if (is_array($forum_list)) {
5860
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5861
                // This is needed because sql3 takes also the deleted forums into account.
5862
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5863
            }
5864
        }
5865
    }
5866
5867
    // Finding the last post information
5868
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5869
    if (!empty($forum_list)) {
5870
        foreach ($forum_list as $key => $value) {
5871
            $lastPost = get_last_post_information($key, api_is_allowed_to_edit());
5872
            if ($lastPost) {
5873
                $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
5874
                $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
5875
                $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
5876
                $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
5877
                $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
5878
                $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
5879
            }
5880
        }
5881
    }
5882
5883
    return $forum_list;
5884
}
5885
5886
/**
5887
 * This function stores which users have to be notified of which forums or threads.
5888
 *
5889
 * @param string $content    does the user want to be notified about a forum or about a thread
5890
 * @param int    $id         the id of the forum or thread
5891
 * @param bool   $addOnly
5892
 * @param array  $userInfo
5893
 * @param array  $courseInfo
5894
 *
5895
 * @return string language variable
5896
 *
5897
 * @author  Patrick Cool <[email protected]>, Ghent University, Belgium
5898
 * @author  Julio Montoya
5899
 *
5900
 * @since   May 2008 v1.8.5
5901
 */
5902
function set_notification($content, $id, $addOnly = false, $userInfo = [], $courseInfo = [])
5903
{
5904
    $userInfo = empty($userInfo) ? api_get_user_info() : $userInfo;
5905
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
5906
    $id = (int) $id;
5907
5908
    if (empty($userInfo) || empty($courseInfo) || empty($id) || empty($content)) {
5909
        return false;
5910
    }
5911
5912
    // Database table definition
5913
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5914
5915
    $course_id = $courseInfo['real_id'];
5916
5917
    // Which database field do we have to store the id in?
5918
    $field = 'thread_id';
5919
    if ($content === 'forum') {
5920
        $field = 'forum_id';
5921
    }
5922
5923
    $userId = $userInfo['user_id'];
5924
5925
    // First we check if the notification is already set for this.
5926
    $sql = "SELECT * FROM $table_notification
5927
            WHERE
5928
                c_id = $course_id AND
5929
                $field = $id AND
5930
                user_id = $userId ";
5931
    $result = Database::query($sql);
5932
    $total = Database::num_rows($result);
5933
5934
    // If the user did not indicate that (s)he wanted to be notified already
5935
    // then we store the notification request (to prevent double notification requests).
5936
    if ($total <= 0) {
5937
        $sql = "INSERT INTO $table_notification (c_id, $field, user_id)
5938
                VALUES ($course_id, '$id','$userId')";
5939
        Database::query($sql);
5940
        Session::erase('forum_notification');
5941
        getNotificationsPerUser(0, true);
5942
5943
        return get_lang('You will be notified of new posts by e-mail.');
5944
    } else {
5945
        if (!$addOnly) {
5946
            $sql = "DELETE FROM $table_notification
5947
                    WHERE
5948
                        c_id = $course_id AND
5949
                        $field = $id AND
5950
                        user_id = $userId ";
5951
            Database::query($sql);
5952
            Session::erase('forum_notification');
5953
            getNotificationsPerUser(0, true);
5954
5955
            return get_lang('You will no longer be notified of new posts by email');
5956
        }
5957
    }
5958
}
5959
5960
/**
5961
 * This function retrieves all the email adresses of the users who wanted to be notified
5962
 * about a new post in a certain forum or thread.
5963
 *
5964
 * @param string $content does the user want to be notified about a forum or about a thread
5965
 * @param int    $id      the id of the forum or thread
5966
 *
5967
 * @return array returns
5968
 *
5969
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5970
 * @author Julio Montoya
5971
 *
5972
 * @version May 2008, dokeos 1.8.5
5973
 *
5974
 * @since May 2008, dokeos 1.8.5
5975
 */
5976
function get_notifications($content, $id)
5977
{
5978
    // Database table definition
5979
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5980
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5981
    $course_id = api_get_course_int_id();
5982
5983
    // Which database field contains the notification?
5984
    $field = 'thread_id';
5985
    if ($content === 'forum') {
5986
        $field = 'forum_id';
5987
    }
5988
5989
    $id = (int) $id;
5990
5991
    $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
5992
            FROM $table_users user, $table_notification notification
5993
            WHERE
5994
                notification.c_id = $course_id AND user.active = 1 AND
5995
                user.user_id = notification.user_id AND
5996
                notification.$field = $id ";
5997
5998
    $result = Database::query($sql);
5999
    $return = [];
6000
6001
    while ($row = Database::fetch_array($result)) {
6002
        $return['user'.$row['user_id']] = ['email' => $row['email'], 'user_id' => $row['user_id']];
6003
    }
6004
6005
    return $return;
6006
}
6007
6008
/**
6009
 * Get all the users who need to receive a notification of a new post (those subscribed to
6010
 * the forum or the thread).
6011
 *
6012
 * @param int $forum_id  the id of the forum
6013
 * @param int $thread_id the id of the thread
6014
 * @param int $post_id   the id of the post
6015
 *
6016
 * @return false|null
6017
 *
6018
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
6019
 *
6020
 * @version May 2008, dokeos 1.8.5
6021
 *
6022
 * @since May 2008, dokeos 1.8.5
6023
 */
6024
function send_notifications(CForumForum $forum, CForumThread $thread, $post_id = 0)
6025
{
6026
    if (!$forum) {
6027
        return false;
6028
    }
6029
6030
    // Users who subscribed to the forum
6031
    $users_to_be_notified_by_forum = get_notifications('forum', $forum->getIid());
6032
6033
    // User who subscribed to the thread
6034
    if (!$thread) {
6035
        $users_to_be_notified_by_thread = get_notifications('thread', $thread->getIid());
6036
    }
6037
6038
    $postInfo = [];
6039
    if (!empty($post_id)) {
6040
        $postInfo = get_post_information($post_id);
6041
    }
6042
6043
    // Merging the two
6044
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
6045
6046
    if (is_array($users_to_be_notified)) {
6047
        foreach ($users_to_be_notified as $value) {
6048
            $userInfo = api_get_user_info($value['user_id']);
6049
            send_mail($userInfo, $forum, $thread, $postInfo);
6050
        }
6051
    }
6052
}
6053
6054
/**
6055
 * Get all the notification subscriptions of the user
6056
 * = which forums and which threads does the user wants to be informed of when a new
6057
 * post is added to this thread.
6058
 *
6059
 * @param int  $user_id the user_id of a user (default = 0 => the current user)
6060
 * @param bool $force   force get the notification subscriptions (even if the information is already in the session
6061
 *
6062
 * @return array
6063
 *
6064
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
6065
 *
6066
 * @version May 2008, dokeos 1.8.5
6067
 *
6068
 * @since May 2008, dokeos 1.8.5
6069
 */
6070
function getNotificationsPerUser($user_id = 0, $force = false, $course_id = 0)
6071
{
6072
    // Database table definition
6073
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
6074
    $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
6075
    if (empty($course_id) || $course_id == -1) {
6076
        return null;
6077
    }
6078
6079
    $user_id = empty($user_id) ? api_get_user_id() : (int) $user_id;
6080
6081
    if (!isset($_SESSION['forum_notification']) ||
6082
        $_SESSION['forum_notification']['course'] != $course_id ||
6083
        $force == true
6084
    ) {
6085
        $_SESSION['forum_notification']['course'] = $course_id;
6086
        $sql = "SELECT * FROM $table_notification
6087
                WHERE c_id = $course_id AND user_id='".$user_id."'";
6088
6089
        $result = Database::query($sql);
6090
        while ($row = Database::fetch_array($result)) {
6091
            if (!is_null($row['forum_id'])) {
6092
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
6093
            }
6094
            if (!is_null($row['thread_id'])) {
6095
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
6096
            }
6097
        }
6098
    }
6099
}
6100
6101
/**
6102
 * This function counts the number of post inside a thread.
6103
 *
6104
 * @param int $thread_id
6105
 *
6106
 * @return int the number of post inside a thread
6107
 *
6108
 * @author Jhon Hinojosa <[email protected]>,
6109
 *
6110
 * @version octubre 2008, dokeos 1.8
6111
 */
6112
function count_number_of_post_in_thread($thread_id)
6113
{
6114
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6115
    $course_id = api_get_course_int_id();
6116
    if (empty($course_id)) {
6117
        return 0;
6118
    }
6119
    $sql = "SELECT count(*) count FROM $table_posts
6120
            WHERE
6121
                c_id = $course_id AND
6122
                thread_id='".intval($thread_id)."' ";
6123
    $result = Database::query($sql);
6124
6125
    $count = 0;
6126
    if (Database::num_rows($result) > 0) {
6127
        $row = Database::fetch_array($result);
6128
        $count = $row['count'];
6129
    }
6130
6131
    return $count;
6132
}
6133
6134
/**
6135
 * This function counts the number of post inside a thread user.
6136
 *
6137
 * @param int $thread_id
6138
 * @param int $user_id
6139
 *
6140
 * @return int the number of post inside a thread user
6141
 */
6142
function count_number_of_post_for_user_thread($thread_id, $user_id)
6143
{
6144
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6145
    $course_id = api_get_course_int_id();
6146
    $sql = "SELECT count(iid) as count
6147
            FROM $table_posts
6148
            WHERE c_id = $course_id AND
6149
                  thread_id=".intval($thread_id)." AND
6150
                  poster_id = ".intval($user_id)." AND visible = 1 ";
6151
    $result = Database::query($sql);
6152
    $count = 0;
6153
    if (Database::num_rows($result) > 0) {
6154
        $count = Database::fetch_array($result);
6155
        $count = $count['count'];
6156
    }
6157
6158
    return $count;
6159
}
6160
6161
/**
6162
 * This function retrieves information of statistical.
6163
 *
6164
 * @param int $thread_id
6165
 * @param int $user_id
6166
 * @param int $course_id
6167
 *
6168
 * @return array the information of statistical
6169
 *
6170
 * @author Jhon Hinojosa <[email protected]>,
6171
 *
6172
 * @version oct 2008, dokeos 1.8
6173
 */
6174
function get_statistical_information($thread_id, $user_id, $course_id)
6175
{
6176
    $result = [];
6177
    $courseInfo = api_get_course_info_by_id($course_id);
6178
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
6179
    $result['post'] = count_number_of_post_in_thread($thread_id);
6180
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
6181
6182
    return $result;
6183
}
6184
6185
/**
6186
 * This function return the posts inside a thread from a given user.
6187
 *
6188
 * @param string $course_code
6189
 * @param int    $thread_id
6190
 * @param int    $user_id
6191
 *
6192
 * @return array posts inside a thread
6193
 *
6194
 * @author Jhon Hinojosa <[email protected]>,
6195
 *
6196
 * @version oct 2008, dokeos 1.8
6197
 */
6198
function get_thread_user_post($course_code, $thread_id, $user_id)
6199
{
6200
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6201
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
6202
    $thread_id = intval($thread_id);
6203
    $user_id = intval($user_id);
6204
    $course_info = api_get_user_info($course_code);
6205
    $course_id = $course_info['real_id'];
6206
6207
    if (empty($course_id)) {
6208
        $course_id = api_get_course_int_id();
6209
    }
6210
    $sql = "SELECT * FROM $table_posts posts
6211
            LEFT JOIN  $table_users users
6212
                ON posts.poster_id=users.user_id
6213
            WHERE
6214
                posts.c_id = $course_id AND
6215
                posts.thread_id='$thread_id'
6216
                AND posts.poster_id='$user_id'
6217
            ORDER BY posts.post_id ASC";
6218
6219
    $result = Database::query($sql);
6220
    $post_list = [];
6221
    while ($row = Database::fetch_array($result)) {
6222
        $row['status'] = '1';
6223
        $post_list[] = $row;
6224
        $sql = "SELECT * FROM $table_posts posts
6225
                LEFT JOIN $table_users users
6226
                ON (posts.poster_id=users.user_id)
6227
                WHERE
6228
                    posts.c_id = $course_id AND
6229
                    posts.thread_id='$thread_id'
6230
                    AND posts.post_parent_id='".$row['post_id']."'
6231
                ORDER BY posts.post_id ASC";
6232
        $result2 = Database::query($sql);
6233
        while ($row2 = Database::fetch_array($result2)) {
6234
            $row2['status'] = '0';
6235
            $post_list[] = $row2;
6236
        }
6237
    }
6238
6239
    return $post_list;
6240
}
6241
6242
/**
6243
 * This function get the name of an thread by id.
6244
 *
6245
 * @param int thread_id
6246
 *
6247
 * @return string
6248
 *
6249
 * @author Christian Fasanando
6250
 * @author Julio Montoya <[email protected]> Adding security
6251
 */
6252
function get_name_thread_by_id($thread_id)
6253
{
6254
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
6255
    $course_id = api_get_course_int_id();
6256
    $sql = "SELECT thread_title
6257
            FROM $t_forum_thread
6258
            WHERE c_id = $course_id AND thread_id = '".intval($thread_id)."' ";
6259
    $result = Database::query($sql);
6260
    $row = Database::fetch_array($result);
6261
6262
    return $row[0];
6263
}
6264
6265
/**
6266
 * This function gets all the post written by an user.
6267
 *
6268
 * @param int    $user_id
6269
 * @param string $course_code
6270
 *
6271
 * @return string
6272
 */
6273
function get_all_post_from_user($user_id, $course_code)
6274
{
6275
    $j = 0;
6276
    $forums = get_forums('', $course_code);
6277
    krsort($forums);
6278
    $forum_results = '';
6279
6280
    foreach ($forums as $forum) {
6281
        if ($forum['visibility'] == 0) {
6282
            continue;
6283
        }
6284
        if ($j <= 4) {
6285
            $threads = get_threads($forum['forum_id']);
6286
6287
            if (is_array($threads)) {
6288
                $i = 0;
6289
                $hand_forums = '';
6290
                $post_counter = 0;
6291
                foreach ($threads as $thread) {
6292
                    if ($thread['visibility'] == 0) {
6293
                        continue;
6294
                    }
6295
                    if ($i <= 4) {
6296
                        $post_list = get_thread_user_post_limit(
6297
                            $course_code,
6298
                            $thread['thread_id'],
6299
                            $user_id,
6300
                            1
6301
                        );
6302
                        $post_counter = count($post_list);
6303
                        if (is_array($post_list) && count($post_list) > 0) {
6304
                            $hand_forums .= '<div id="social-thread">';
6305
                            $hand_forums .= Display::return_icon(
6306
                                'thread.png',
6307
                                get_lang('Thread'),
6308
                                '',
6309
                                ICON_SIZE_MEDIUM
6310
                            );
6311
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
6312
                            $hand_forums .= '</div>';
6313
6314
                            foreach ($post_list as $posts) {
6315
                                $hand_forums .= '<div id="social-post">';
6316
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
6317
                                $hand_forums .= '<br / >';
6318
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
6319
                                $hand_forums .= '</div>';
6320
                                $hand_forums .= '<br / >';
6321
                            }
6322
                        }
6323
                    }
6324
                    $i++;
6325
                }
6326
                $forum_results .= '<div id="social-forum">';
6327
                $forum_results .= '<div class="clear"></div><br />';
6328
                $forum_results .= '<div id="social-forum-title">'.
6329
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum['forum_title'], STUDENT).
6330
                    '<div style="float:right;margin-top:-35px">
6331
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($course_code).'&forum='.$forum['forum_id'].' " >'.
6332
                    get_lang('See forum').'
6333
                        </a>
6334
                     </div></div>';
6335
                $forum_results .= '<br / >';
6336
                if ($post_counter > 0) {
6337
                    $forum_results .= $hand_forums;
6338
                }
6339
                $forum_results .= '</div>';
6340
            }
6341
            $j++;
6342
        }
6343
    }
6344
6345
    return $forum_results;
6346
}
6347
6348
/**
6349
 * @param string $course_code
6350
 * @param int    $thread_id
6351
 * @param int    $user_id
6352
 * @param int    $limit
6353
 *
6354
 * @return array
6355
 */
6356
function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
6357
{
6358
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
6359
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
6360
6361
    $course_info = api_get_course_info($course_code);
6362
    $course_id = $course_info['real_id'];
6363
6364
    $sql = "SELECT * FROM $table_posts posts
6365
            LEFT JOIN  $table_users users
6366
                ON posts.poster_id=users.user_id
6367
            WHERE
6368
                posts.c_id = $course_id AND
6369
                posts.thread_id='".Database::escape_string($thread_id)."' AND
6370
                posts.poster_id='".Database::escape_string($user_id)."'
6371
            ORDER BY posts.post_id DESC LIMIT $limit ";
6372
    $result = Database::query($sql);
6373
    $post_list = [];
6374
    while ($row = Database::fetch_array($result)) {
6375
        $row['status'] = '1';
6376
        $post_list[] = $row;
6377
    }
6378
6379
    return $post_list;
6380
}
6381
6382
/**
6383
 * @param string $userId
6384
 * @param array  $courseInfo
6385
 * @param int    $sessionId
6386
 *
6387
 * @return array
6388
 */
6389
function getForumCreatedByUser($userId, $courseInfo, $sessionId)
6390
{
6391
    if (empty($userId) || empty($courseInfo)) {
6392
        return [];
6393
    }
6394
6395
    $courseId = $courseInfo['real_id'];
6396
    $items = api_get_item_property_list_by_tool_by_user(
6397
        $userId,
6398
        'forum',
6399
        $courseId,
6400
        $sessionId
6401
    );
6402
6403
    $forumList = [];
6404
    if (!empty($items)) {
6405
        foreach ($items as $forum) {
6406
            $forumInfo = get_forums(
6407
                $forum['ref'],
6408
                $courseInfo['code'],
6409
                true,
6410
                $sessionId
6411
            );
6412
            if (!empty($forumInfo) && isset($forumInfo['forum_title'])) {
6413
                $forumList[] = [
6414
                    $forumInfo['forum_title'],
6415
                    api_get_local_time($forum['insert_date']),
6416
                    api_get_local_time($forum['lastedit_date']),
6417
                ];
6418
            }
6419
        }
6420
    }
6421
6422
    return $forumList;
6423
}
6424
6425
/**
6426
 * This function builds an array of all the posts in a given thread
6427
 * where the key of the array is the post_id
6428
 * It also adds an element children to the array which itself is an array
6429
 * that contains all the id's of the first-level children.
6430
 *
6431
 * @return array $rows containing all the information on the posts of a thread
6432
 *
6433
 * @author Patrick Cool <[email protected]>, Ghent University
6434
 */
6435
function calculate_children($rows)
6436
{
6437
    $sorted_rows = [0 => []];
6438
    if (!empty($rows)) {
6439
        foreach ($rows as $row) {
6440
            $rows_with_children[$row['post_id']] = $row;
6441
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
6442
        }
6443
6444
        $rows = $rows_with_children;
6445
        forumRecursiveSort($rows, $sorted_rows);
6446
        unset($sorted_rows[0]);
6447
    }
6448
6449
    return $sorted_rows;
6450
}
6451
6452
/**
6453
 * @param $rows
6454
 * @param $threads
6455
 * @param int $seed
6456
 * @param int $indent
6457
 */
6458
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
6459
{
6460
    if ($seed > 0) {
6461
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
6462
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
6463
        $indent++;
6464
    }
6465
6466
    if (isset($rows[$seed]['children'])) {
6467
        foreach ($rows[$seed]['children'] as $child) {
6468
            forumRecursiveSort($rows, $threads, $child, $indent);
6469
        }
6470
    }
6471
}
6472
6473
/**
6474
 * Update forum attachment data, used to update comment and post ID.
6475
 *
6476
 * @param $array array (field => value) to update forum attachment row
6477
 * @param $id attach ID to find row to update
6478
 * @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...
6479
 *
6480
 * @return int number of affected rows
6481
 */
6482
function editAttachedFile($array, $id, $courseId = null)
6483
{
6484
    // Init variables
6485
    $setString = '';
6486
    $id = (int) $id;
6487
    $courseId = (int) $courseId;
6488
    if (empty($courseId)) {
6489
        // $courseId can be null, use api method
6490
        $courseId = api_get_course_int_id();
6491
    }
6492
    /*
6493
     * Check if Attachment ID and Course ID are greater than zero
6494
     * and array of field values is not empty
6495
     */
6496
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
6497
        foreach ($array as $key => &$item) {
6498
            $item = Database::escape_string($item);
6499
            $setString .= $key.' = "'.$item.'", ';
6500
        }
6501
        // Delete last comma
6502
        $setString = substr($setString, 0, strlen($setString) - 2);
6503
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6504
        $sql = "UPDATE $forumAttachmentTable
6505
                SET $setString WHERE c_id = $courseId AND id = $id";
6506
        $result = Database::query($sql);
6507
        if ($result !== false) {
6508
            $affectedRows = Database::affected_rows($result);
6509
            if ($affectedRows > 0) {
6510
                /*
6511
                 * If exist in $_SESSION variable, then delete them from it
6512
                 * because they would be deprecated
6513
                 */
6514
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
6515
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
6516
                }
6517
            }
6518
6519
            return $affectedRows;
6520
        }
6521
    }
6522
6523
    return 0;
6524
}
6525
6526
/**
6527
 * Return a table where the attachments will be set.
6528
 *
6529
 * @param int $postId Forum Post ID
6530
 *
6531
 * @return string The Forum Attachments Ajax Table
6532
 */
6533
function getAttachmentsAjaxTable($postId = 0)
6534
{
6535
    $postId = (int) $postId;
6536
    $courseId = api_get_course_int_id();
6537
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6538
    $fileDataContent = '';
6539
    // Update comment to show if form did not pass validation
6540
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
6541
        // 'file_ids is the name from forum attachment ajax form
6542
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
6543
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
6544
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
6545
            ) {
6546
                // If exist forum attachment then update into $_SESSION data
6547
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
6548
            }
6549
        }
6550
    }
6551
6552
    // Get data to fill into attachment files table
6553
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6554
        is_array($_SESSION['forum']['upload_file'][$courseId])
6555
    ) {
6556
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
6557
        foreach ($uploadedFiles as $k => $uploadedFile) {
6558
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
6559
                // Buil html table including an input with attachmentID
6560
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
6561
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
6562
                    $uploadedFile['delete'].'</td>'.
6563
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
6564
            } else {
6565
                /*
6566
                 * If attachment data is empty, then delete it from $_SESSION
6567
                 * because could generate and empty row into html table
6568
                 */
6569
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
6570
            }
6571
        }
6572
    }
6573
    $style = empty($fileDataContent) ? 'display: none;' : '';
6574
    // Forum attachment Ajax table
6575
    $fileData = '
6576
    <div class="control-group " style="'.$style.'">
6577
        <label class="control-label">'.get_lang('Attachments list').'</label>
6578
        <div class="controls">
6579
            <table id="attachmentFileList" class="files data_table span10">
6580
                <tr>
6581
                    <th>'.get_lang('Filename').'</th>
6582
                    <th>'.get_lang('Size').'</th>
6583
                    <th>'.get_lang('Status').'</th>
6584
                    <th>'.get_lang('Comment').'</th>
6585
                    <th>'.get_lang('Delete').'</th>
6586
                </tr>
6587
                '.$fileDataContent.'
6588
            </table>
6589
        </div>
6590
    </div>';
6591
6592
    return $fileData;
6593
}
6594
6595
/**
6596
 * Return an array of prepared attachment data to build forum attachment table
6597
 * Also, save this array into $_SESSION to do available the attachment data.
6598
 *
6599
 * @param int $forumId
6600
 * @param int $threadId
6601
 * @param int $postId
6602
 * @param int $attachId
6603
 * @param int $courseId
6604
 *
6605
 * @return array
6606
 */
6607
function getAttachedFiles(
6608
    $forumId,
6609
    $threadId,
6610
    $postId = 0,
6611
    $attachId = 0,
6612
    $courseId = 0
6613
) {
6614
    $forumId = (int) $forumId;
6615
    $courseId = (int) $courseId;
6616
    $attachId = (int) $attachId;
6617
    $postId = (int) $postId;
6618
    $threadId = !empty($threadId) ? intval($threadId) : isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : '';
6619
    if (empty($courseId)) {
6620
        // $courseId can be null, use api method
6621
        $courseId = api_get_course_int_id();
6622
    }
6623
    if (empty($forumId)) {
6624
        if (!empty($_REQUEST['forum'])) {
6625
            $forumId = (int) $_REQUEST['forum'];
6626
        } else {
6627
            // if forum ID is empty, cannot generate delete url
6628
6629
            return [];
6630
        }
6631
    }
6632
    // Check if exist at least one of them to filter forum attachment select query
6633
    if (empty($postId) && empty($attachId)) {
6634
        return [];
6635
    } elseif (empty($postId)) {
6636
        $filter = "AND iid = $attachId";
6637
    } elseif (empty($attachId)) {
6638
        $filter = "AND post_id = $postId";
6639
    } else {
6640
        $filter = "AND post_id = $postId AND iid = $attachId";
6641
    }
6642
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6643
    $sql = "SELECT iid, comment, filename, path, size
6644
            FROM $forumAttachmentTable
6645
            WHERE c_id = $courseId $filter";
6646
    $result = Database::query($sql);
6647
    $json = [];
6648
    if ($result !== false && Database::num_rows($result) > 0) {
6649
        while ($row = Database::fetch_array($result, 'ASSOC')) {
6650
            // name contains an URL to download attachment file and its filename
6651
            $json['name'] = Display::url(
6652
                api_htmlentities($row['filename']),
6653
                api_get_path(WEB_CODE_PATH).'forum/download.php?file='.$row['path'].'&'.api_get_cidreq(),
6654
                ['target' => '_blank', 'class' => 'attachFilename']
6655
            );
6656
            $json['id'] = $row['iid'];
6657
            $json['comment'] = $row['comment'];
6658
            // Format file size
6659
            $json['size'] = format_file_size($row['size']);
6660
            // Check if $row is consistent
6661
            if (!empty($row) && is_array($row)) {
6662
                // Set result as success and bring delete URL
6663
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded.'));
6664
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
6665
                $json['delete'] = Display::url(
6666
                    Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL),
6667
                    $url,
6668
                    ['class' => 'deleteLink']
6669
                );
6670
            } else {
6671
                // If not, set an exclamation result
6672
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
6673
            }
6674
            // Store array data into $_SESSION
6675
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
6676
        }
6677
    }
6678
6679
    return $json;
6680
}
6681
6682
/**
6683
 * Clear forum attachment data stored in $_SESSION,
6684
 * If is not defined post, it will clear all forum attachment data from course.
6685
 *
6686
 * @param int $postId   -1 : Clear all attachments from course stored in $_SESSION
6687
 *                      0 : Clear attachments from course, except from temporal post "0"
6688
 *                      but without delete them from file system and database
6689
 *                      Other values : Clear attachments from course except specified post
6690
 *                      and delete them from file system and database
6691
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
6692
 *
6693
 * @return array
6694
 */
6695
function clearAttachedFiles($postId = 0, $courseId = 0)
6696
{
6697
    // Init variables
6698
    $courseId = (int) $courseId;
6699
    $postId = (int) $postId;
6700
    $array = [];
6701
    if (empty($courseId)) {
6702
        // $courseId can be null, use api method
6703
        $courseId = api_get_course_int_id();
6704
    }
6705
    if ($postId === -1) {
6706
        // If post ID is -1 then delete course's attachment data from $_SESSION
6707
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
6708
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
6709
            unset($_SESSION['forum']['upload_file'][$courseId]);
6710
        }
6711
    } else {
6712
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6713
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6714
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
6715
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
6716
                if (!in_array($attachId, $attachIds)) {
6717
                    // If attach ID is not into specified post, delete attachment
6718
                    // Save deleted attachment ID
6719
                    $array[] = $attachId;
6720
                    if ($postId !== 0) {
6721
                        // Post 0 is temporal, delete them from file system and DB
6722
                        delete_attachment(0, $attachId);
6723
                    }
6724
                    // Delete attachment data from $_SESSION
6725
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
6726
                }
6727
            }
6728
        }
6729
    }
6730
6731
    return $array;
6732
}
6733
6734
/**
6735
 * Returns an array of forum attachment ids into a course and forum post.
6736
 *
6737
 * @param int $postId
6738
 * @param int $courseId
6739
 *
6740
 * @return array
6741
 */
6742
function getAttachmentIdsByPostId($postId, $courseId = 0)
6743
{
6744
    $array = [];
6745
    $courseId = (int) $courseId;
6746
    $postId = (int) $postId;
6747
    if (empty($courseId)) {
6748
        // $courseId can be null, use api method
6749
        $courseId = api_get_course_int_id();
6750
    }
6751
    if ($courseId > 0) {
6752
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6753
        $sql = "SELECT id FROM $forumAttachmentTable
6754
                WHERE c_id = $courseId AND post_id = $postId";
6755
        $result = Database::query($sql);
6756
        if ($result !== false && Database::num_rows($result) > 0) {
6757
            while ($row = Database::fetch_array($result, 'ASSOC')) {
6758
                $array[] = $row['id'];
6759
            }
6760
        }
6761
    }
6762
6763
    return $array;
6764
}
6765
6766
/**
6767
 * Check if the forum category exists looking for its title.
6768
 *
6769
 * @param string $title     The forum category title
6770
 * @param int    $courseId  The course ID
6771
 * @param int    $sessionId Optional. The session ID
6772
 *
6773
 * @return bool
6774
 */
6775
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
6776
{
6777
    $sessionId = (int) $sessionId;
6778
    $courseId = (int) $courseId;
6779
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
6780
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
6781
6782
    $fakeFrom = "$forumCategoryTable fc
6783
        INNER JOIN $itemProperty ip ";
6784
6785
    if ($sessionId === 0) {
6786
        $fakeFrom .= "
6787
            ON (
6788
                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)
6789
            )
6790
        ";
6791
    } else {
6792
        $fakeFrom .= "
6793
            ON (
6794
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
6795
            )
6796
        ";
6797
    }
6798
6799
    $resultData = Database::select(
6800
        'fc.*',
6801
        $fakeFrom,
6802
        [
6803
            'where' => [
6804
                'ip.visibility != ? AND ' => 2,
6805
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
6806
                'fc.session_id = ? AND ' => $sessionId,
6807
                'fc.cat_title = ? AND ' => $title,
6808
                'fc.c_id = ?' => $courseId,
6809
            ],
6810
        ],
6811
        'first'
6812
    );
6813
6814
    if (empty($resultData)) {
6815
        return false;
6816
    }
6817
6818
    return $resultData;
6819
}
6820
6821
/**
6822
 * @param CForumForum $forum
6823
 * @param array $row
6824
 * @param bool  $addWrapper
6825
 *
6826
 * @return string
6827
 */
6828
function getPostStatus(CForumForum $forum, $row, $addWrapper = true)
6829
{
6830
    $statusIcon = '';
6831
    if ($forum->isModerated()) {
6832
        if ($addWrapper) {
6833
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
6834
        }
6835
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
6836
6837
        $addUrl = false;
6838
        $showStatus = false;
6839
        if (api_is_allowed_to_edit(false, true)) {
6840
            $addUrl = true;
6841
        } else {
6842
            if ($row['user_id'] == api_get_user_id()) {
6843
                $showStatus = true;
6844
            }
6845
        }
6846
6847
        $label = '';
6848
        $icon = '';
6849
        $buttonType = '';
6850
        switch ($row['status']) {
6851
            case CForumPost::STATUS_VALIDATED:
6852
                $label = get_lang('Validated');
6853
                $icon = 'check-circle';
6854
                $buttonType = 'success';
6855
                break;
6856
            case CForumPost::STATUS_WAITING_MODERATION:
6857
                $label = get_lang('Waiting for moderation');
6858
                $icon = 'warning';
6859
                $buttonType = 'warning';
6860
                break;
6861
            case CForumPost::STATUS_REJECTED:
6862
                $label = get_lang('Rejected');
6863
                $icon = 'minus-circle';
6864
                $buttonType = 'danger';
6865
                break;
6866
        }
6867
6868
        if ($addUrl) {
6869
            $statusIcon .= Display::toolbarButton(
6870
                $label.'&nbsp;',
6871
                'javascript:void(0)',
6872
                $icon,
6873
                $buttonType,
6874
                ['class' => 'change_post_status']
6875
            );
6876
        } else {
6877
            if ($showStatus) {
6878
                $statusIcon .= Display::label(
6879
                    Display::returnFontAwesomeIcon($icon).$label,
6880
                    $buttonType
6881
                );
6882
            }
6883
        }
6884
6885
        if ($addWrapper) {
6886
            $statusIcon .= '</span>';
6887
        }
6888
    }
6889
6890
    return $statusIcon;
6891
}
6892
6893
/**
6894
 * @param array $forumInfo
6895
 * @param int   $threadId
6896
 * @param int   $status
6897
 *
6898
 * @return mixed
6899
 */
6900
function getCountPostsWithStatus($status, $forumInfo, $threadId = null)
6901
{
6902
    $em = Database::getManager();
6903
    $criteria = Criteria::create();
6904
    $criteria
6905
        ->where(Criteria::expr()->eq('status', $status))
6906
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
6907
        ->andWhere(Criteria::expr()->eq('visible', 1))
6908
    ;
6909
6910
    if (!empty($threadId)) {
6911
        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
6912
    }
6913
6914
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
6915
    $qb->select('count(p.iid)')
6916
        ->addCriteria($criteria);
6917
6918
    return $qb->getQuery()->getSingleScalarResult();
6919
}
6920
6921
/**
6922
 * @param array $forum
6923
 * @param array $post
6924
 *
6925
 * @return bool
6926
 */
6927
function postIsEditableByStudent($forum, $post)
6928
{
6929
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6930
        return true;
6931
    }
6932
6933
    if ($forum['moderated'] == 1) {
6934
        if (is_null($post['status'])) {
6935
            return true;
6936
        } else {
6937
            return in_array(
6938
                $post['status'],
6939
                [
6940
                    CForumPost::STATUS_WAITING_MODERATION,
6941
                    CForumPost::STATUS_REJECTED,
6942
                ]
6943
            );
6944
        }
6945
    } else {
6946
        return true;
6947
    }
6948
}
6949
6950
/**
6951
 * @param int $postId
6952
 *
6953
 * @return bool
6954
 */
6955
function savePostRevision($postId)
6956
{
6957
    $postData = get_post_information($postId);
6958
6959
    if (empty($postData)) {
6960
        return false;
6961
    }
6962
6963
    $userId = api_get_user_id();
6964
6965
    if ($postData['poster_id'] != $userId) {
6966
        return false;
6967
    }
6968
6969
    $status = (int) !postNeedsRevision($postId);
6970
    $extraFieldValue = new ExtraFieldValue('forum_post');
6971
    $params = [
6972
        'item_id' => $postId,
6973
        'extra_ask_for_revision' => ['extra_ask_for_revision' => $status],
6974
    ];
6975
    if (empty($status)) {
6976
        unset($params['extra_ask_for_revision']);
6977
    }
6978
    $extraFieldValue->saveFieldValues(
6979
        $params,
6980
        true,
6981
        false,
6982
        ['ask_for_revision']
6983
    );
6984
}
6985
6986
/**
6987
 * @param int $postId
6988
 *
6989
 * @return string
6990
 */
6991
function getPostRevision($postId)
6992
{
6993
    $extraFieldValue = new ExtraFieldValue('forum_post');
6994
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6995
        $postId,
6996
        'revision_language'
6997
    );
6998
    $revision = '';
6999
    if ($value && isset($value['value'])) {
7000
        $revision = $value['value'];
7001
    }
7002
7003
    return $revision;
7004
}
7005
7006
/**
7007
 * @param int $postId
7008
 *
7009
 * @return bool
7010
 */
7011
function postNeedsRevision($postId)
7012
{
7013
    $extraFieldValue = new ExtraFieldValue('forum_post');
7014
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
7015
        $postId,
7016
        'ask_for_revision'
7017
    );
7018
    $hasRevision = false;
7019
    if ($value && isset($value['value'])) {
7020
        return $value['value'] == 1;
7021
    }
7022
7023
    return $hasRevision;
7024
}
7025
7026
/**
7027
 * @param int   $postId
7028
 * @param array $threadInfo
7029
 *
7030
 * @return string
7031
 */
7032
function getAskRevisionButton($postId, $threadInfo)
7033
{
7034
    if (api_get_configuration_value('allow_forum_post_revisions') === false) {
7035
        return '';
7036
    }
7037
7038
    $postId = (int) $postId;
7039
7040
    $status = 'btn-default';
7041
    if (postNeedsRevision($postId)) {
7042
        $status = 'btn-success';
7043
    }
7044
7045
    return Display::url(
7046
        get_lang('Ask for a revision'),
7047
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
7048
        api_get_cidreq().'&action=ask_revision&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
7049
        ['class' => "btn $status", 'title' => get_lang('Ask for a revision')]
7050
    );
7051
}
7052
7053
/**
7054
 * @param int   $postId
7055
 * @param array $threadInfo
7056
 *
7057
 * @return string
7058
 */
7059
function giveRevisionButton($postId, $threadInfo)
7060
{
7061
    $postId = (int) $postId;
7062
7063
    return Display::toolbarButton(
7064
        get_lang('Give revision'),
7065
        api_get_path(WEB_CODE_PATH).'forum/reply.php?'.api_get_cidreq().'&'.http_build_query(
7066
            [
7067
                'forum' => $threadInfo['forum_id'],
7068
                'thread' => $threadInfo['thread_id'],
7069
                'post' => $postId = (int) $postId,
7070
                'action' => 'replymessage',
7071
                'give_revision' => 1,
7072
            ]
7073
        ),
7074
        'reply',
7075
        'primary',
7076
        ['id' => "reply-to-post-{$postId}"]
7077
    );
7078
}
7079
7080
/**
7081
 * @param int   $postId
7082
 * @param array $threadInfo
7083
 *
7084
 * @return string
7085
 */
7086
function getReportButton($postId, $threadInfo)
7087
{
7088
    $postId = (int) $postId;
7089
7090
    return Display::url(
7091
        Display::returnFontAwesomeIcon('flag'),
7092
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
7093
        api_get_cidreq().'&action=report&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
7094
        ['class' => 'btn btn-danger', 'title' => get_lang('Report')]
7095
    );
7096
}
7097
7098
/**
7099
 * @return bool
7100
 */
7101
function reportAvailable()
7102
{
7103
    $extraFieldValue = new ExtraFieldValue('course');
7104
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
7105
        api_get_course_int_id(),
7106
        'allow_forum_report_button'
7107
    );
7108
    $allowReport = false;
7109
    if ($value && isset($value['value']) && $value['value'] == 1) {
7110
        $allowReport = true;
7111
    }
7112
7113
    return $allowReport;
7114
}
7115
7116
/**
7117
 * @return array
7118
 */
7119
function getReportRecipients()
7120
{
7121
    $extraFieldValue = new ExtraFieldValue('course');
7122
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
7123
        api_get_course_int_id(),
7124
        'forum_report_recipients'
7125
    );
7126
    $users = [];
7127
    if ($value && isset($value['value'])) {
7128
        $usersType = explode(';', $value['value']);
7129
7130
        foreach ($usersType as $type) {
7131
            switch ($type) {
7132
                case 'teachers':
7133
                    $teachers = CourseManager::get_teacher_list_from_course_code(api_get_course_id());
7134
                    if (!empty($teachers)) {
7135
                        $users = array_merge($users, array_column($teachers, 'user_id'));
7136
                    }
7137
                break;
7138
                case 'admins':
7139
                    $admins = UserManager::get_all_administrators();
7140
                    if (!empty($admins)) {
7141
                        $users = array_merge($users, array_column($admins, 'user_id'));
7142
                    }
7143
                    break;
7144
                case 'community_managers':
7145
                    $managers = api_get_configuration_value('community_managers_user_list');
7146
                    if (!empty($managers) && isset($managers['users'])) {
7147
                        $users = array_merge($users, $managers['users']);
7148
                    }
7149
                    break;
7150
            }
7151
        }
7152
7153
        $users = array_unique(array_filter($users));
7154
    }
7155
7156
    return $users;
7157
}
7158
7159
/**
7160
 * @param int   $postId
7161
 * @param array $forumInfo
7162
 * @param array $threadInfo
7163
 *
7164
 * @return bool
7165
 */
7166
function reportPost($postId, $forumInfo, $threadInfo)
7167
{
7168
    if (!reportAvailable()) {
7169
        return false;
7170
    }
7171
7172
    if (empty($forumInfo) || empty($threadInfo)) {
7173
        return false;
7174
    }
7175
7176
    $postId = (int) $postId;
7177
7178
    $postData = get_post_information($postId);
7179
    $currentUser = api_get_user_info();
7180
7181
    if (!empty($postData)) {
7182
        $users = getReportRecipients();
7183
        if (!empty($users)) {
7184
            $url = api_get_path(WEB_CODE_PATH).
7185
                'forum/viewthread.php?forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'].'&'.api_get_cidreq().'&post_id='.$postId.'#post_id_'.$postId;
7186
            $postLink = Display::url(
7187
                $postData['post_title'],
7188
                $url
7189
            );
7190
            $subject = get_lang('Post reported');
7191
            $content = sprintf(
7192
                get_lang('User %s has reported the message %s in the forum %s'),
7193
                $currentUser['complete_name'],
7194
                $postLink,
7195
                $forumInfo['forum_title']
7196
            );
7197
            foreach ($users as $userId) {
7198
                MessageManager::send_message_simple($userId, $subject, $content);
7199
            }
7200
        }
7201
    }
7202
}
7203