Passed
Push — master ( f9e6b3...5e8c5a )
by Julito
09:39
created

display_forum_search_results()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\GradebookLink;
6
use Chamilo\CoreBundle\Entity\User;
7
use Chamilo\CoreBundle\Framework\Container;
8
use Chamilo\CourseBundle\Entity\CForumAttachment;
9
use Chamilo\CourseBundle\Entity\CForumCategory;
10
use Chamilo\CourseBundle\Entity\CForumForum;
11
use Chamilo\CourseBundle\Entity\CForumNotification;
12
use Chamilo\CourseBundle\Entity\CForumPost;
13
use Chamilo\CourseBundle\Entity\CForumThread;
14
use Chamilo\CoreBundle\Entity\Course;
15
use Chamilo\CourseBundle\Entity\CGroup;
16
use ChamiloSession as Session;
17
use Doctrine\Common\Collections\Criteria;
18
use Symfony\Component\HttpFoundation\File\UploadedFile;
19
20
/*
21
 * These files are a complete rework of the forum. The database structure is
22
 * based on phpBB but all the code is rewritten. A lot of new functionalities
23
 * are added:
24
 * - forum categories and forums can be sorted up or down, locked or made invisible
25
 * - consistent and integrated forum administration
26
 * - forum options:     are students allowed to edit their post?
27
 *                         moderation of posts (approval)
28
 *                         reply only forums (students cannot create new threads)
29
 *                         multiple forums per group
30
 * - sticky messages
31
 * - new view option: nested view
32
 * - quoting a message.
33
 *
34
 * @package chamilo.forum
35
 *
36
 * @todo convert into a class
37
 */
38
define('FORUM_NEW_POST', 0);
39
getNotificationsPerUser();
40
41
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
42
$htmlHeadXtra[] = '<script>
43
44
function check_unzip() {
45
    if (document.upload.unzip.checked){
46
        document.upload.if_exists[0].disabled=true;
47
        document.upload.if_exists[1].checked=true;
48
        document.upload.if_exists[2].disabled=true;
49
    } else {
50
        document.upload.if_exists[0].checked=true;
51
        document.upload.if_exists[0].disabled=false;
52
        document.upload.if_exists[2].disabled=false;
53
    }
54
}
55
function setFocus() {
56
    $("#title_file").focus();
57
}
58
</script>';
59
// The next javascript script is to manage ajax upload file
60
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
61
62
// Recover Thread ID, will be used to generate delete attachment URL to do ajax
63
$threadId = isset($_REQUEST['thread']) ? (int) ($_REQUEST['thread']) : 0;
64
$forumId = isset($_REQUEST['forum']) ? (int) ($_REQUEST['forum']) : 0;
65
66
$ajaxUrl = api_get_path(WEB_AJAX_PATH).'forum.ajax.php?'.api_get_cidreq();
67
// The next javascript script is to delete file by ajax
68
$htmlHeadXtra[] = '<script>
69
$(function () {
70
    $(document).on("click", ".deleteLink", function(e) {
71
        e.preventDefault();
72
        e.stopPropagation();
73
        var l = $(this);
74
        var id = l.closest("tr").attr("id");
75
        var filename = l.closest("tr").find(".attachFilename").html();
76
        if (confirm("'.get_lang('Are you sure to delete').'", filename)) {
77
            $.ajax({
78
                type: "POST",
79
                url: "'.$ajaxUrl.'&a=delete_file&attachId=" + id +"&thread='.$threadId.'&forum='.$forumId.'",
80
                dataType: "json",
81
                success: function(data) {
82
                    if (data.error == false) {
83
                        l.closest("tr").remove();
84
                        if ($(".files td").length < 1) {
85
                            $(".files").closest(".control-group").hide();
86
                        }
87
                    }
88
                }
89
            })
90
        }
91
    });
92
});
93
</script>';
94
95
function handleForum($url)
96
{
97
    $id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : null;
98
99
    if (api_is_allowed_to_edit(false, true)) {
100
        //if is called from a learning path lp_id
101
        $lp_id = isset($_REQUEST['lp_id']) ? (int) $_REQUEST['lp_id'] : null;
102
        $content = isset($_REQUEST['content']) ? $_REQUEST['content'] : '';
103
        $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
104
105
        $repo = null;
106
107
        switch ($content) {
108
            case 'forumcategory':
109
                $repo = Container::getForumCategoryRepository();
110
                break;
111
            case 'forum':
112
                $repo = Container::getForumRepository();
113
                break;
114
            case 'thread':
115
                $repo = Container::getForumThreadRepository();
116
                break;
117
        }
118
119
        if ($repo && $id) {
120
            $resource = $repo->find($id);
121
        }
122
123
        switch ($action) {
124
            case 'add_forum':
125
                $formContent = forumForm(null, $lp_id);
126
127
                return $formContent;
128
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
129
            case 'edit_forum':
130
                $repo = Container::getForumRepository();
131
                $resource = $repo->find($id);
132
                $formContent = forumForm($resource, $lp_id);
133
134
                return $formContent;
135
                break;
136
            case 'add_category':
137
                $formContent = show_add_forumcategory_form([], $lp_id);
138
139
                return $formContent;
140
                break;
141
            case 'edit_category':
142
                $repo = Container::getForumCategoryRepository();
143
                $category = $repo->find($id);
144
                $formContent = editForumCategoryForm($category);
145
146
                return $formContent;
147
                break;
148
            case 'notify':
149
                if (0 != api_get_session_id() &&
150
                    false == api_is_allowed_to_session_edit(false, true)
151
                ) {
152
                    api_not_allowed();
153
                }
154
                $message = set_notification($content, $id);
155
                Display::addFlash(Display::return_message($message, 'confirm', false));
156
157
                header('Location: '.$url);
158
                exit;
159
                break;
160
            case 'lock':
161
            case 'unlock':
162
                if ($resource) {
163
                    if ('lock' === $action) {
164
                        $locked = 1;
165
                        $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');
166
                    } else {
167
                        $locked = 0;
168
                        $message = get_lang('Unlocked: learners can post new messages in this forum category, forum or thread');
169
                    }
170
171
                    $resource->setLocked($locked);
172
                    $repo->update($resource);
173
174
                    Display::addFlash(
175
                        Display::return_message($message, 'confirmation', false)
176
                    );
177
                }
178
179
                header('Location: '.$url);
180
                exit;
181
                break;
182
            case 'move':
183
                move_up_down($content, $_REQUEST['direction'] ?? '', $id);
184
                header('Location: '.$url);
185
                exit;
186
                break;
187
            case 'move_thread':
188
                $message = move_thread_form();
189
190
                return $message;
191
                break;
192
            case 'visible':
193
            case 'invisible':
194
                if ('visible' === $action) {
195
                    $repo->setVisibilityPublished($resource);
196
                } else {
197
                    $repo->setVisibilityPending($resource);
198
                }
199
200
                if ('visible' === $action) {
201
                    handle_mail_cue($content, $id);
202
                }
203
204
                Display::addFlash(
205
                    Display::return_message(get_lang('Updated'), 'confirmation', false)
206
                );
207
                header('Location: '.$url);
208
                exit;
209
                break;
210
            case 'delete':
211
                $locked = api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD);
212
                if ($resource && false === $locked) {
213
                    $repo->delete($resource);
214
215
                    if ('thread' === $content) {
216
                        $return_message = get_lang('Thread deleted');
217
                        Skill::deleteSkillsFromItem($id, ITEM_TYPE_FORUM_THREAD);
218
                    }
219
220
                    $link_info = GradebookUtils::isResourceInCourseGradebook(
221
                        api_get_course_id(),
222
                        5,
223
                        $id,
224
                        api_get_session_id()
225
                    );
226
227
                    if (false !== $link_info) {
228
                        $link_id = $link_info['id'];
229
                        GradebookUtils::remove_resource_from_course_gradebook($link_id);
230
                    }
231
                }
232
233
                Display::addFlash(Display::return_message(get_lang('Forum category deleted'), 'confirmation', false));
234
                header('Location: '.$url);
235
                exit;
236
                break;
237
        }
238
    }
239
}
240
241
/**
242
 * This function displays the form that is used to add a forum category.
243
 *
244
 * @param int $lp_id Learning path ID
245
 *
246
 * @return string
247
 *
248
 * @author Patrick Cool <[email protected]>, Ghent University
249
 * @author Juan Carlos Raña Trabado (return to lp_id)
250
 *
251
 * @version may 2011, Chamilo 1.8.8
252
 */
253
function show_add_forumcategory_form($lp_id)
254
{
255
    $form = new FormValidator(
256
        'forumcategory',
257
        'post',
258
        'index.php?'.api_get_cidreq().'&action=add_category'
259
    );
260
    // hidden field if from learning path
261
    $form->addElement('hidden', 'lp_id', $lp_id);
262
    $form->addElement('hidden', 'action', 'add_category');
263
    // Setting the form elements.
264
    $form->addElement('header', get_lang('Add forum category'));
265
    $form->addElement('text', 'forum_category_title', get_lang('Title'), ['autofocus']);
266
    $form->addElement(
267
        'html_editor',
268
        'forum_category_comment',
269
        get_lang('Description'),
270
        null,
271
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
272
    );
273
274
    $extraField = new ExtraField('forum_category');
275
    $extraField->addElements(
276
        $form,
277
        null,
278
        [], //exclude
279
        false, // filter
280
        false, // tag as select
281
        [], //show only fields
282
        [], // order fields
283
        [] // extra data
284
    );
285
286
    $form->addButtonCreate(get_lang('Create category'), 'SubmitForumCategory');
287
288
    // Setting the rules.
289
    $form->addRule('forum_category_title', get_lang('Required field'), 'required');
290
291
    // The validation or display
292
    if ($form->validate()) {
293
        $check = Security::check_token('post');
294
        if ($check) {
295
            $values = $form->exportValues();
296
            store_forumcategory($values);
297
        }
298
        Security::clear_token();
299
    } else {
300
        $token = Security::get_token();
301
        $form->addElement('hidden', 'sec_token');
302
        $form->setConstants(['sec_token' => $token]);
303
304
        return $form->returnForm();
305
    }
306
}
307
308
function forumForm(CForumForum $forum = null, $lp_id)
309
{
310
    $_course = api_get_course_info();
311
    // The header for the form
312
    $form_title = get_lang('Add a forum');
313
    $action = 'add_forum';
314
    $id = 0;
315
    if ($forum) {
316
        $id = $forum->getIid();
317
        $action = 'edit_forum';
318
        $form_title = get_lang('Edit forum');
319
    }
320
321
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq().'&action='.$action.'&id='.$id);
322
    $form->addHidden('action', $action);
323
    $form->addHeader($form_title);
324
325
    // We have a hidden field if we are editing.
326
    if ($forum) {
327
        $form->addElement('hidden', 'forum_id', $id);
328
    }
329
    $lp_id = (int) $lp_id;
330
331
    // hidden field if from learning path
332
    $form->addElement('hidden', 'lp_id', $lp_id);
333
334
    // The title of the forum
335
    $form->addElement('text', 'forum_title', get_lang('Title'), ['autofocus']);
336
337
    // The comment of the forum.
338
    $form->addElement(
339
        'html_editor',
340
        'forum_comment',
341
        get_lang('Description'),
342
        null,
343
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
344
    );
345
346
    // Dropdown list: Forum categories
347
    $forum_categories = get_forum_categories();
348
    $forum_categories_titles = [];
349
    foreach ($forum_categories as $value) {
350
        $forum_categories_titles[$value->getCatId()] = $value->getCatTitle();
351
    }
352
    $form->addElement(
353
        'select',
354
        'forum_category',
355
        get_lang('Create in category'),
356
        $forum_categories_titles
357
    );
358
    $form->applyFilter('forum_category', 'html_filter');
359
360
    if (COURSE_VISIBILITY_OPEN_WORLD == $_course['visibility']) {
361
        // This is for horizontal
362
        $group = [];
363
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('Yes'), 1);
364
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('No'), 0);
365
        $form->addGroup($group, 'allow_anonymous_group', get_lang('Allow anonymous posts?'));
366
    }
367
368
    $form->addButtonAdvancedSettings('advanced_params');
369
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
370
371
    $form->addDateTimePicker(
372
        'start_time',
373
        [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')],
374
        ['id' => 'start_time']
375
    );
376
377
    $form->addDateTimePicker(
378
        'end_time',
379
        [get_lang('Closing date'), get_lang('Closing dateComment')],
380
        ['id' => 'end_time']
381
    );
382
383
    $form->addRule(
384
        ['start_time', 'end_time'],
385
        get_lang('Start date must be before the end date'),
386
        'compare_datetime_text',
387
        '< allow_empty'
388
    );
389
390
    $group = [];
391
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('Yes'), 1);
392
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('No'), 0);
393
    $form->addGroup($group, 'moderated', get_lang('Moderated forum'));
394
395
    $group = [];
396
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('Yes'), 1);
397
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('No'), 0);
398
    $form->addGroup($group, 'students_can_edit_group', get_lang('Can learners edit their own posts?'));
399
400
    $group = [];
401
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Approval'), 1);
402
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Direct'), 0);
403
404
    $group = [];
405
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('Yes'), 1);
406
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('No'), 0);
407
408
    $group = [];
409
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('Yes'), 1);
410
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('No'), 0);
411
    $form->addGroup($group, 'allow_new_threads_group', get_lang('Allow users to start new threads'));
412
413
    $group = [];
414
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
415
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
416
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
417
    $form->addGroup($group, 'default_view_type_group', get_lang('Default view type'));
418
419
    // Drop down list: Groups
420
    $groups = GroupManager::get_group_list();
421
    $groups_titles[0] = get_lang('Not a group forum');
422
    foreach ($groups as $key => $value) {
423
        $groups_titles[$value['iid']] = $value['name'];
424
    }
425
    $form->addElement('select', 'group_forum', get_lang('For Group'), $groups_titles);
426
427
    // Public or private group forum
428
    $group = [];
429
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Public access (access authorized to any member of the course)'), 'public');
430
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Private access (access authorized to group members only)'), 'private');
431
    $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'));
432
433
    // Forum image
434
    $form->addProgress();
435
    /*
436
    if ($forum) {
437
        $baseImagePath = api_get_course_path().'/upload/forum/images/'.$inputvalues['forum_image'];
438
        $image_path = api_get_path(WEB_COURSE_PATH).$baseImagePath;
439
        $sysImagePath = api_get_path(SYS_COURSE_PATH).$baseImagePath;
440
441
        if (file_exists($sysImagePath)) {
442
            $show_preview_image = Display::img(
443
                $image_path,
444
                null,
445
                ['class' => 'img-responsive']
446
            );
447
            $form->addElement('label', get_lang('Preview image'), $show_preview_image);
448
            $form->addElement('checkbox', 'remove_picture', null, get_lang('Remove picture'));
449
        }
450
    }
451
    $forum_image = isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
452
    $form->addElement('file', 'picture', ('' != $forum_image ? get_lang('Update Image') : get_lang('Add image')));
453
    $form->addRule(
454
        'picture',
455
        get_lang('Only PNG, JPG or GIF images allowed'),
456
        'filetype',
457
        ['jpg', 'jpeg', 'png', 'gif']
458
    );*/
459
460
    //$forumId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
461
    //$skillList = Skill::addSkillsToForm($form, ITEM_TYPE_FORUM, $forumId);
462
463
    $form->addElement('html', '</div>');
464
465
    // The OK button
466
    if ($forum) {
467
        $form->addButtonUpdate(get_lang('Edit forum'), 'SubmitForum');
468
    } else {
469
        $form->addButtonCreate(get_lang('Create forum'), 'SubmitForum');
470
    }
471
472
    // setting the rules
473
    $form->addRule('forum_title', get_lang('Required field'), 'required');
474
    $form->addRule('forum_category', get_lang('Required field'), 'required');
475
476
    $defaultSettingAllowNewThreads = api_get_default_tool_setting('forum', 'allow_new_threads', 0);
477
478
    // Settings the defaults
479
    if (null === $forum) {
480
        $defaults['moderated']['moderated'] = 0;
481
        $defaults['allow_anonymous_group']['allow_anonymous'] = 0;
482
        $defaults['students_can_edit_group']['students_can_edit'] = 0;
483
        $defaults['approval_direct_group']['approval_direct'] = 0;
484
        $defaults['allow_attachments_group']['allow_attachments'] = 1;
485
        $defaults['allow_new_threads_group']['allow_new_threads'] = $defaultSettingAllowNewThreads;
486
        $defaults['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
487
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = 'public';
488
        if (isset($_GET['forumcategory'])) {
489
            $defaults['forum_category'] = Security::remove_XSS($_GET['forumcategory']);
490
        }
491
    } else {
492
        // the default values when editing = the data in the table
493
        $defaults['forum_id'] = $forum->getIid();
494
        $defaults['forum_title'] = prepare4display($forum->getForumTitle());
495
        $defaults['forum_comment'] = prepare4display($forum->getForumComment());
496
        $defaults['start_time'] = api_get_local_time($forum->getStartTime());
497
        $defaults['end_time'] = api_get_local_time($forum->getEndTime());
498
        $defaults['moderated']['moderated'] = $forum->isModerated();
499
        $defaults['forum_category'] = $forum->getForumCategory()->getIid();
500
        $defaults['allow_anonymous_group']['allow_anonymous'] = $forum->getAllowAnonymous();
501
        $defaults['students_can_edit_group']['students_can_edit'] = $forum->getAllowEdit();
502
        $defaults['approval_direct_group']['approval_direct'] = $forum->getApprovalDirectPost();
503
        $defaults['allow_attachments_group']['allow_attachments'] = $forum->getAllowAttachments();
504
        $defaults['allow_new_threads_group']['allow_new_threads'] = $forum->getAllowNewThreads();
505
        $defaults['default_view_type_group']['default_view_type'] = $forum->getDefaultView();
506
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = $forum->getForumGroupPublicPrivate();
507
        $defaults['group_forum'] = $forum->getForumOfGroup();
508
    }
509
510
    $form->setDefaults($defaults);
511
    // Validation or display
512
    if ($form->validate()) {
513
        $check = Security::check_token('post');
514
        if ($check) {
515
            $values = $form->getSubmitValues();
516
            $forumId = store_forum($values, '', true);
517
            if ($forumId) {
518
                // Skill::saveSkills($form, ITEM_TYPE_FORUM, $forumId);
519
                if (isset($values['forum_id'])) {
520
                    Display::addFlash(Display::return_message(get_lang('The forum has been modified'), 'confirmation'));
521
                } else {
522
                    Display::addFlash(Display::return_message(get_lang('The forum has been added'), 'confirmation'));
523
                }
524
            }
525
            $url = api_get_path(WEB_CODE_PATH).'forum/index.php?'.api_get_cidreq();
526
            header('Location: '.$url);
527
            exit;
528
        }
529
        Security::clear_token();
530
    } else {
531
        $token = Security::get_token();
532
        $form->addElement('hidden', 'sec_token');
533
        $form->setConstants(['sec_token' => $token]);
534
535
        return $form->returnForm();
536
    }
537
}
538
539
/**
540
 * This function deletes the forum image if exists.
541
 *
542
 * @param int $forum_id forum id
543
 *
544
 * @return bool true if success
545
 *
546
 * @author Julio Montoya <[email protected]>
547
 *
548
 * @version february 2006, dokeos 1.8
549
 */
550
function delete_forum_image($forum_id)
551
{
552
    throw new Exception('delete_forum_image');
553
    /*$table_forums = Database::get_course_table(TABLE_FORUM);
554
    $course_id = api_get_course_int_id();
555
    $forum_id = (int) $forum_id;
556
557
    $sql = "SELECT forum_image FROM $table_forums
558
            WHERE forum_id = $forum_id AND c_id = $course_id";
559
    $result = Database::query($sql);
560
    $row = Database::fetch_array($result);
561
    if ('' != $row['forum_image']) {
562
        $file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
563
        if (file_exists($file)) {
564
            unlink($file);
565
        }
566
567
        return true;
568
    } else {
569
        return false;
570
    }*/
571
}
572
573
function editForumCategoryForm(CForumCategory $category)
574
{
575
    $categoryId = $category->getIid();
576
    $form = new FormValidator(
577
        'forumcategory',
578
        'post',
579
        'index.php?action=edit_category&'.api_get_cidreq().'&id='.$categoryId
580
    );
581
    // Setting the form elements.
582
    $form->addElement('header', '', get_lang('Edit forumCategory'));
583
584
    $form->addElement('hidden', 'action', 'edit_category');
585
    $form->addElement('hidden', 'forum_category_id');
586
    $form->addElement('text', 'forum_category_title', get_lang('Title'));
587
588
    $form->addElement(
589
        'html_editor',
590
        'forum_category_comment',
591
        get_lang('Comment'),
592
        null,
593
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
594
    );
595
596
    $extraField = new ExtraField('forum_category');
597
    $returnParams = $extraField->addElements(
598
        $form,
599
        $categoryId,
600
        [], //exclude
601
        false, // filter
602
        false, // tag as select
603
        [], //show only fields
604
        [], // order fields
605
        [] // extra data
606
    );
607
608
    $form->addButtonUpdate(get_lang('Edit category'), 'SubmitEdit forumCategory');
609
610
    // Setting the default values.
611
    $defaultvalues['forum_category_id'] = $categoryId;
612
    $defaultvalues['forum_category_title'] = $category->getCatTitle();
613
    $defaultvalues['forum_category_comment'] = $category->getCatComment();
614
    $form->setDefaults($defaultvalues);
615
616
    // Setting the rules.
617
    $form->addRule('forum_category_title', get_lang('Required field'), 'required');
618
619
    // Validation or display
620
    if ($form->validate()) {
621
        $check = Security::check_token('post');
622
        if ($check) {
623
            $values = $form->exportValues();
624
            store_forumcategory($values);
625
        }
626
        Security::clear_token();
627
    } else {
628
        $token = Security::get_token();
629
        $form->addElement('hidden', 'sec_token');
630
        $form->setConstants(['sec_token' => $token]);
631
632
        return $form->returnForm();
633
    }
634
}
635
636
/**
637
 * This function stores the forum category in the database.
638
 * The new category is added to the end.
639
 *
640
 * @param array $values
641
 * @param array $courseInfo
642
 * @param bool  $showMessage
643
 *
644
 * @return CForumCategory
645
 */
646
function store_forumcategory($values, $courseInfo = [], $showMessage = true)
647
{
648
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
649
    $course_id = $courseInfo['real_id'];
650
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
651
652
    // Find the max cat_order. The new forum category is added at the end => max cat_order + &
653
    $sql = "SELECT MAX(cat_order) as sort_max
654
            FROM $table_categories
655
            WHERE c_id = $course_id";
656
    $result = Database::query($sql);
657
    $row = Database::fetch_array($result);
658
    $new_max = $row['sort_max'] + 1;
659
    $session_id = api_get_session_id();
660
    $clean_cat_title = $values['forum_category_title'];
661
    $last_id = null;
662
    $repo = Container::getForumCategoryRepository();
663
664
    $message = '';
665
    if (isset($values['forum_category_id'])) {
666
        /** @var CForumCategory $category */
667
        $category = $repo->find($values['forum_category_id']);
668
        $category
669
            ->setCatComment(isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '')
670
            ->setCatTitle($values['forum_category_title'])
671
        ;
672
        $repo->update($category);
673
        $message = get_lang('The forum category has been modified');
674
675
        $logInfo = [
676
            'tool' => TOOL_FORUM,
677
            'action' => 'update-forumcategory',
678
            'action_details' => 'forumcategory',
679
            'info' => $clean_cat_title,
680
        ];
681
        Event::registerLog($logInfo);
682
683
        $values['item_id'] = $values['forum_category_id'];
684
    } else {
685
        $course = api_get_course_entity($course_id);
686
        $session = api_get_session_entity($session_id);
687
688
        $category = new CForumCategory();
689
        $category
690
            ->setCatTitle($clean_cat_title)
691
            ->setCatComment(isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '')
692
            ->setCatOrder($new_max)
693
            ->setCId($course_id)
694
            ->setSessionId($session_id)
695
            ->setParent($course)
696
            ->addCourseLink($course, $session)
697
        ;
698
        $repo->create($category);
699
700
        $last_id = $category->getIid();
701
        if ($last_id > 0) {
702
            $sql = "UPDATE $table_categories SET cat_id = $last_id WHERE iid = $last_id";
703
            Database::query($sql);
704
            $message = get_lang('The forum category has been added');
705
        }
706
707
        $logInfo = [
708
            'tool' => TOOL_FORUM,
709
            'action' => 'new-forumcategory',
710
            'action_details' => 'forumcategory',
711
            'info' => $clean_cat_title,
712
        ];
713
        Event::registerLog($logInfo);
714
715
        $values['item_id'] = $last_id;
716
    }
717
718
    $extraFieldValue = new ExtraFieldValue('forum_category');
719
    $extraFieldValue->saveFieldValues($values);
720
721
    if ($showMessage) {
722
        Display::addFlash(Display::return_message($message, 'confirmation'));
723
    }
724
725
    return $category;
726
}
727
728
/**
729
 * This function stores the forum in the database. The new forum is added to the end.
730
 *
731
 * @param array $values
732
 * @param array $courseInfo
733
 * @param bool  $returnId
734
 *
735
 * @return string language variable
736
 */
737
function store_forum($values, $courseInfo = [], $returnId = false)
738
{
739
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
740
    $courseId = $courseInfo['real_id'];
741
    $session_id = api_get_session_id();
742
    $table_forums = Database::get_course_table(TABLE_FORUM);
743
744
    // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
745
    if (null === $values['forum_category']) {
746
        $new_max = null;
747
    } else {
748
        $sql = "SELECT MAX(forum_order) as sort_max
749
                FROM $table_forums
750
                WHERE
751
                    c_id = $courseId AND
752
                    forum_category='".Database::escape_string($values['forum_category'])."'";
753
        $result = Database::query($sql);
754
        $row = Database::fetch_array($result);
755
        $new_max = $row['sort_max'] + 1;
756
    }
757
758
    // Forum images
759
    $has_attachment = false;
760
    $image_moved = true;
761
    if (!empty($_FILES['picture']['name'])) {
762
        $upload_ok = process_uploaded_file($_FILES['picture']);
763
        $has_attachment = true;
764
    }
765
766
    // Remove existing picture if it was requested.
767
    if (!empty($_POST['remove_picture'])) {
768
        delete_forum_image($values['forum_id']);
769
    }
770
771
    $new_file_name = '';
772
    if (isset($upload_ok)) {
773
        if ($has_attachment) {
774
            throw new Exception('$has_attachment');
775
            /*$course_dir = $courseInfo['path'].'/upload/forum/images';
776
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
777
            $updir = $sys_course_path.$course_dir;
778
            // Try to add an extension to the file if it hasn't one.
779
            $new_file_name = add_ext_on_mime(
780
                Database::escape_string($_FILES['picture']['name']),
781
                $_FILES['picture']['type']
782
            );
783
            if (!filter_extension($new_file_name)) {
784
                //Display::addFlash(Display::return_message(get_lang('File upload failed: this file extension or file type is prohibited'), 'error'));
785
                $image_moved = false;
786
            } else {
787
                $file_extension = explode('.', $_FILES['picture']['name']);
788
                $file_extension = strtolower($file_extension[count($file_extension) - 1]);
789
                $new_file_name = uniqid('').'.'.$file_extension;
790
                $new_path = $updir.'/'.$new_file_name;
791
                $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
792
                // Storing the attachments if any
793
                if ($result) {
794
                    $image_moved = true;
795
                }
796
            }*/
797
        }
798
    }
799
800
    $repo = Container::getForumRepository();
801
802
    if (!isset($values['forum_id'])) {
803
        $forum = new CForumForum();
804
        $forum
805
            ->setCId($courseId)
806
            ->setSessionId($session_id)
807
            ->setForumOrder(isset($new_max) ? $new_max : null)
808
        ;
809
    } else {
810
        /** @var CForumForum $forum */
811
        $forum = $repo->find($values['forum_id']);
812
    }
813
814
    $forumCategory = null;
815
    if (!empty($values['forum_category'])) {
816
        $repoForumCategory = Container::getForumCategoryRepository();
817
        $forumCategory = $repoForumCategory->find($values['forum_category']);
818
    }
819
    //'forum_image' => $new_file_name,
820
    $forum
821
        ->setForumTitle($values['forum_title'])
822
        ->setForumComment($values['forum_comment'] ?? null)
823
        ->setForumCategory($forumCategory)
824
        ->setAllowAnonymous($values['allow_anonymous_group']['allow_anonymous'] ?? null)
825
        ->setAllowEdit($values['students_can_edit_group']['students_can_edit'] ?? null)
826
        ->setApprovalDirectPost($values['approval_direct_group']['approval_direct'] ?? null)
827
        ->setAllowAttachments($values['allow_attachments_group']['allow_attachments'] ?? null)
828
        ->setAllowNewThreads($values['allow_new_threads_group']['allow_new_threads'] ?? null)
829
        ->setDefaultView($values['default_view_type_group']['default_view_type'] ?? null)
830
        ->setForumOfGroup($values['group_forum'] ?? null)
831
        ->setForumGroupPublicPrivate($values['public_private_group_forum_group']['public_private_group_forum'] ?? '')
832
        ->setModerated($values['moderated']['moderated'] ?? null)
833
        ->setStartTime(!empty($values['start_time']) ? api_get_utc_datetime($values['start_time'], true, true) : null)
834
        ->setEndTime(!empty($values['end_time']) ? api_get_utc_datetime($values['end_time'], true, true) : null)
835
        ->setSessionId($session_id)
836
        ->setLpId($values['lp_id'] ?? 0)
837
    ;
838
839
    $course = api_get_course_entity($courseId);
840
    $session = api_get_session_entity($session_id);
841
842
    if (isset($values['forum_id'])) {
843
        // Update.
844
        $repo->update($forum);
845
846
        if (isset($upload_ok)) {
847
            if ($has_attachment) {
848
                //$params['forum_image'] = $new_file_name;
849
            }
850
        }
851
852
        if (isset($values['remove_picture']) && 1 == $values['remove_picture']) {
853
            /*$params['forum_image'] = '';
854
            delete_forum_image($values['forum_id']);*/
855
        }
856
857
        // Move groups from one group to another
858
        if (isset($values['group_forum']) && false) {
859
            $forumData = get_forums($values['forum_id']);
860
            $currentGroupId = $forumData['forum_of_group'];
861
            if ($currentGroupId != $values['group_forum']) {
862
                $threads = get_threads($values['forum_id']);
863
                $toGroupId = 'NULL';
864
                if (!empty($values['group_forum'])) {
865
                    $toGroupId = $values['group_forum'];
866
                }
867
                $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
868
                foreach ($threads as $thread) {
869
                    /*$sql = "UPDATE $tableItemProperty
870
                            SET to_group_id = $toGroupId
871
                            WHERE
872
                                tool = '".TOOL_FORUM_THREAD."' AND
873
                                ref = ".$thread['thread_id'].' AND
874
                                c_id = '.$courseId;
875
                    Database::query($sql);
876
877
                    $posts = getPosts(
878
                        $forumData,
879
                        $thread['thread_id']
880
                    );*/
881
882
                    /*foreach ($posts as $post) {
883
                        $postId = $post['post_id'];
884
                        $attachMentList = getAllAttachment($postId);
885
                        if (!empty($attachMentList)) {
886
                            foreach ($attachMentList as $attachMent) {
887
                                $sql = "UPDATE $tableItemProperty
888
                                        SET to_group_id = $toGroupId
889
                                        WHERE
890
                                            tool = '".TOOL_FORUM_ATTACH."' AND
891
                                            ref = ".$attachMent['iid'].' AND
892
                                            c_id = '.$courseId;
893
                                Database::query($sql);
894
                            }
895
                        }
896
897
                        $sql = "UPDATE $tableItemProperty
898
                                SET to_group_id = $toGroupId
899
                                WHERE
900
                                    tool = '".TOOL_FORUM_POST."' AND
901
                                    ref = $postId AND
902
                                    c_id = $courseId";
903
                        Database::query($sql);
904
                    }*/
905
                }
906
            }
907
        }
908
909
        /*
910
        api_item_property_update(
911
            $courseInfo,
912
            TOOL_FORUM,
913
            Database::escape_string($values['forum_id']),
914
            'ForumUpdated',
915
            api_get_user_id(),
916
            $groupInfo
917
        );*/
918
919
        $return_message = get_lang('The forum has been modified');
920
        $forumId = $forum->getIid();
921
922
        $logInfo = [
923
            'tool' => TOOL_FORUM,
924
            'tool_id' => $values['forum_id'],
925
            'action' => 'update-forum',
926
            'action_details' => 'forum',
927
            'info' => $values['forum_title'],
928
        ];
929
        Event::registerLog($logInfo);
930
    } else {
931
        if ($image_moved) {
932
            $new_file_name = isset($new_file_name) ? $new_file_name : '';
933
        }
934
        $forum
935
            ->setParent($forumCategory)
936
            ->addCourseLink($course, $session);
937
        $repo->create($forum);
938
939
        $forumId = $forum->getIid();
940
        if ($forumId > 0) {
941
            $courseCode = $courseInfo['code'];
942
            $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications');
943
944
            $status = STUDENT;
945
            if (!empty($session_id)) {
946
                $status = 0;
947
            }
948
            if (1 === $subscribe) {
949
                $userList = CourseManager::get_user_list_from_course_code(
950
                    $courseCode,
951
                    $session_id,
952
                    null,
953
                    null,
954
                    $status
955
                );
956
                foreach ($userList as $userInfo) {
957
                    set_notification('forum', $forumId, false, $userInfo, $courseInfo);
958
                }
959
            }
960
961
            /*api_item_property_update(
962
                $courseInfo,
963
                TOOL_FORUM,
964
                $forumId,
965
                'ForumAdded',
966
                api_get_user_id(),
967
                $groupInfo
968
            );
969
970
            api_set_default_visibility(
971
                $forumId,
972
                TOOL_FORUM,
973
                $group_id,
974
                $courseInfo
975
            );*/
976
977
            $logInfo = [
978
                'tool' => TOOL_FORUM,
979
                'tool_id' => $forumId,
980
                'action' => 'new-forum',
981
                'action_details' => 'forum',
982
                'info' => $values['forum_title'],
983
            ];
984
            Event::registerLog($logInfo);
985
        }
986
        $return_message = get_lang('The forum has been added');
987
    }
988
989
    if ($returnId) {
990
        return $forumId;
991
    }
992
993
    return $return_message;
994
}
995
996
function deletePost(CForumPost $post)
997
{
998
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
999
    $course_id = api_get_course_int_id();
1000
    $em = Database::getManager();
1001
    if ($post) {
1002
        $em
1003
            ->createQuery('
1004
                UPDATE ChamiloCourseBundle:CForumPost p
1005
                SET p.postParentId = :parent_of_deleted_post
1006
                WHERE
1007
                    p.cId = :course AND
1008
                    p.postParentId = :post AND
1009
                    p.thread = :thread_of_deleted_post AND
1010
                    p.forum = :forum_of_deleted_post
1011
            ')
1012
            ->execute([
1013
                'parent_of_deleted_post' => $post->getPostParentId(),
1014
                'course' => $course_id,
1015
                'post' => $post->getIid(),
1016
                'thread_of_deleted_post' => $post->getThread() ? $post->getThread()->getIid() : 0,
1017
                'forum_of_deleted_post' => $post->getForum(),
1018
            ]);
1019
1020
        $attachments = $post->getAttachments();
1021
        if (!empty($attachments)) {
1022
            foreach ($attachments as $attachment) {
1023
                $em->remove($attachment);
1024
            }
1025
        }
1026
1027
        $em->remove($post);
1028
        $em->flush();
1029
    }
1030
1031
    $last_post_of_thread = check_if_last_post_of_thread($_GET['thread']);
1032
1033
    if (is_array($last_post_of_thread)) {
1034
        // Decreasing the number of replies for this thread and also changing the last post information.
1035
        $sql = "UPDATE $table_threads
1036
                SET
1037
                    thread_replies = thread_replies - 1,
1038
                    thread_last_post = ".(int) ($last_post_of_thread['iid']).",
1039
                    thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
1040
                WHERE c_id = $course_id AND iid = ".(int) ($_GET['thread']);
1041
        Database::query($sql);
1042
        Display::addFlash(Display::return_message(get_lang('Post has been deleted')));
1043
    }
1044
    if (!$last_post_of_thread) {
1045
        // We deleted the very single post of the thread so we need to delete the entry in the thread table also.
1046
        $sql = "DELETE FROM $table_threads
1047
                WHERE c_id = $course_id AND iid = ".(int) ($_GET['thread']);
1048
        Database::query($sql);
1049
1050
        Display::addFlash(Display::return_message(get_lang('Special Post Deleted')));
1051
    }
1052
}
1053
1054
/**
1055
 * This function gets the all information of the last (=most recent) post of the thread
1056
 * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date.
1057
 *
1058
 * @param int $thread_id id of the thread we want to know the last post of
1059
 *
1060
 * @return array an array or bool if there is a last post found, false if there is
1061
 *               no post entry linked to that thread => thread will be deleted
1062
 *
1063
 * @author Patrick Cool <[email protected]>, Ghent University
1064
 *
1065
 * @version february 2006, dokeos 1.8
1066
 */
1067
function check_if_last_post_of_thread($thread_id)
1068
{
1069
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1070
    $course_id = api_get_course_int_id();
1071
    $sql = "SELECT * FROM $table_posts
1072
            WHERE thread_id = ".(int) $thread_id.'
1073
            ORDER BY post_date DESC';
1074
    $result = Database::query($sql);
1075
    if (Database::num_rows($result) > 0) {
1076
        return Database::fetch_array($result);
1077
    }
1078
1079
    return false;
1080
}
1081
1082
/**
1083
 * @param string $content                   Type of content forum category, forum, thread, post
1084
 * @param int    $id                        the id of the content we want to make invisible
1085
 * @param int    $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
1086
 * @param array  $additional_url_parameters
1087
 *
1088
 * @return string HTML
1089
 */
1090
function return_visible_invisible_icon(
1091
    $content,
1092
    $id,
1093
    $current_visibility_status,
1094
    $additional_url_parameters = []
1095
) {
1096
    $html = '';
1097
    $id = (int) $id;
1098
    $current_visibility_status = (int) $current_visibility_status;
1099
1100
    if (1 == $current_visibility_status) {
1101
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1102
        if (is_array($additional_url_parameters)) {
1103
            foreach ($additional_url_parameters as $key => $value) {
1104
                $html .= $key.'='.$value.'&';
1105
            }
1106
        }
1107
        $html .= 'action=invisible&content='.$content.'&id='.$id.'">'.
1108
            Display::return_icon('visible.png', get_lang('MakeInvisible'), [], ICON_SIZE_SMALL).'</a>';
1109
    }
1110
    if (0 == $current_visibility_status) {
1111
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1112
        if (is_array($additional_url_parameters)) {
1113
            foreach ($additional_url_parameters as $key => $value) {
1114
                $html .= $key.'='.$value.'&';
1115
            }
1116
        }
1117
        $html .= 'action=visible&content='.$content.'&id='.$id.'">'.
1118
            Display::return_icon('invisible.png', get_lang('Make Visible'), [], ICON_SIZE_SMALL).'</a>';
1119
    }
1120
1121
    return $html;
1122
}
1123
1124
/**
1125
 * @param $content
1126
 * @param $id
1127
 * @param $current_lock_status
1128
 * @param string $additional_url_parameters
1129
 *
1130
 * @return string
1131
 */
1132
function return_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters = '')
1133
{
1134
    $html = '';
1135
    $id = (int) $id;
1136
    //check if the forum is blocked due
1137
    if ('thread' == $content) {
1138
        if (api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD)) {
1139
            return $html.Display::return_icon(
1140
                'lock_na.png',
1141
                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.'),
1142
                [],
1143
                ICON_SIZE_SMALL
1144
            );
1145
        }
1146
    }
1147
    if ('1' == $current_lock_status) {
1148
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1149
        if (is_array($additional_url_parameters)) {
1150
            foreach ($additional_url_parameters as $key => $value) {
1151
                $html .= $key.'='.$value.'&';
1152
            }
1153
        }
1154
        $html .= 'action=unlock&content='.$content.'&id='.$id.'">'.
1155
            Display::return_icon('lock.png', get_lang('Unlock'), [], ICON_SIZE_SMALL).'</a>';
1156
    }
1157
    if ('0' == $current_lock_status) {
1158
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1159
        if (is_array($additional_url_parameters)) {
1160
            foreach ($additional_url_parameters as $key => $value) {
1161
                $html .= $key.'='.$value.'&';
1162
            }
1163
        }
1164
        $html .= 'action=lock&content='.$content.'&id='.$id.'">'.
1165
            Display::return_icon('unlock.png', get_lang('Lock'), [], ICON_SIZE_SMALL).'</a>';
1166
    }
1167
1168
    return $html;
1169
}
1170
1171
/**
1172
 * This function takes care of the display of the up and down icon.
1173
 *
1174
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1175
 * @param int    $id      is the id of the item we want to display the icons for
1176
 * @param array  $list    is an array of all the items. All items in this list should have
1177
 *                        an up and down icon except for the first (no up icon) and the last (no down icon)
1178
 *                        The key of this $list array is the id of the item.
1179
 *
1180
 * @return string HTML
1181
 */
1182
function return_up_down_icon($content, $id, $list)
1183
{
1184
    $id = (int) $id;
1185
    $total_items = count($list);
1186
    $position = 0;
1187
    $internal_counter = 0;
1188
    $forumCategory = isset($_GET['forumcategory']) ? Security::remove_XSS($_GET['forumcategory']) : null;
1189
1190
    if (is_array($list)) {
1191
        foreach ($list as $item) {
1192
            $internal_counter++;
1193
            if ($id == $item->getIid()) {
1194
                $position = $internal_counter;
1195
            }
1196
        }
1197
    }
1198
1199
    if ($position > 1) {
1200
        $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').'">'.
1201
            Display::return_icon('up.png', get_lang('Move up'), [], ICON_SIZE_SMALL).'</a>';
1202
    } else {
1203
        $return_value = Display::return_icon('up_na.png', '-', [], ICON_SIZE_SMALL);
1204
    }
1205
1206
    if ($position < $total_items) {
1207
        $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').'" >'.
1208
            Display::return_icon('down.png', get_lang('Move down'), [], ICON_SIZE_SMALL).'</a>';
1209
    } else {
1210
        $return_value .= Display::return_icon('down_na.png', '-', [], ICON_SIZE_SMALL);
1211
    }
1212
1213
    return $return_value;
1214
}
1215
1216
/**
1217
 * This function moves a forum or a forum category up or down.
1218
 *
1219
 * @param string $content   is it that we want to make (in)visible: forum category, forum, thread, post
1220
 * @param string $direction we want to move it up or down
1221
 * @param int    $id        id of the content we want to make invisible
1222
 *
1223
 * @return string language variable
1224
 *
1225
 * @todo consider removing the table_item_property calls here but this can
1226
 * prevent unwanted side effects when a forum does not have an entry in
1227
 * the item_property table but does have one in the forum table.
1228
 *
1229
 * @author Patrick Cool <[email protected]>, Ghent University
1230
 *
1231
 * @version february 2006, dokeos 1.8
1232
 */
1233
function move_up_down($content, $direction, $id)
1234
{
1235
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1236
    $table_forums = Database::get_course_table(TABLE_FORUM);
1237
    $course_id = api_get_course_int_id();
1238
    $id = (int) $id;
1239
1240
    // Determine which field holds the sort order.
1241
    if ('forumcategory' === $content) {
1242
        $table = $table_categories;
1243
        $sort_column = 'cat_order';
1244
        $id_column = 'cat_id';
1245
        $sort_column = 'cat_order';
1246
    } elseif ('forum' === $content) {
1247
        $table = $table_forums;
1248
        $sort_column = 'forum_order';
1249
        $id_column = 'forum_id';
1250
        $sort_column = 'forum_order';
1251
        // We also need the forum_category of this forum.
1252
        $sql = "SELECT forum_category FROM $table_forums
1253
                WHERE c_id = $course_id AND forum_id = ".$id;
1254
        $result = Database::query($sql);
1255
        $row = Database::fetch_array($result);
1256
        $forum_category = $row['forum_category'];
1257
    } else {
1258
        return false;
1259
    }
1260
1261
    // Determine the need for sorting ascending or descending order.
1262
    if ('down' === $direction) {
1263
        $sort_direction = 'ASC';
1264
    } elseif ('up' === $direction) {
1265
        $sort_direction = 'DESC';
1266
    } else {
1267
        return false;
1268
    }
1269
1270
    // The SQL statement
1271
    if ('forumcategory' === $content) {
1272
        $sql = "SELECT *
1273
                FROM $table_categories forum_categories
1274
                WHERE
1275
                    forum_categories.c_id = $course_id
1276
                ORDER BY forum_categories.cat_order $sort_direction";
1277
    }
1278
    if ('forum' === $content) {
1279
        $sql = "SELECT *
1280
            FROM $table
1281
            WHERE
1282
                c_id = $course_id AND
1283
                forum_category='".Database::escape_string($forum_category)."'
1284
            ORDER BY forum_order $sort_direction";
1285
    }
1286
    // Finding the items that need to be switched.
1287
    $result = Database::query($sql);
1288
    $found = false;
1289
    $next_sort = '';
1290
    $this_sort = '';
1291
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1292
        //var_dump($content, $row, $id_column, $sort_column);
1293
        if ($found) {
1294
            $next_id = $row[$id_column];
1295
            $next_sort = $row[$sort_column];
1296
            $found = false;
1297
        }
1298
        if ($id == $row[$id_column]) {
1299
            $this_id = $id;
1300
            $this_sort = $row[$sort_column];
1301
            $found = true;
1302
        }
1303
    }
1304
1305
    if ('forum' === $content && $next_sort) {
1306
        $repo = Container::getForumRepository();
1307
        /** @var CForumForum $forum */
1308
        $forum = $repo->find($id);
1309
        $forum->setForumOrder($next_sort);
1310
        $repo->update($forum);
1311
1312
        Display::addFlash(Display::return_message(get_lang('Updated')));
1313
    } else {
1314
        if ($next_sort) {
1315
            $repo = Container::getForumCategoryRepository();
1316
            /** @var CForumCategory $forum */
1317
            $category = $repo->find($id);
1318
            if ($category) {
1319
                $category->setCatOrder($next_sort);
1320
                $repo->update($category);
1321
1322
                Display::addFlash(Display::return_message(get_lang('Updated')));
1323
            }
1324
        }
1325
    }
1326
}
1327
1328
/**
1329
 * Retrieve all the information off the forum categories (or one specific) for the current course.
1330
 * The categories are sorted according to their sorting order (cat_order.
1331
 *
1332
 * @param int $courseId  Optional. The course ID
1333
 * @param int $sessionId Optional. The session ID
1334
 *
1335
 * @return CForumCategory[]
1336
 */
1337
function get_forum_categories($courseId = 0, $sessionId = 0)
1338
{
1339
    $repo = Container::getForumCategoryRepository();
1340
1341
    $course = api_get_course_entity($courseId);
1342
    $session = api_get_session_entity($sessionId);
1343
1344
    $qb = $repo->getResources(api_get_user_entity(api_get_user_id()), $course->getResourceNode(), $course, $session);
1345
1346
    return $qb->getQuery()->getResult();
1347
}
1348
1349
/**
1350
 * This function retrieves all the fora in a given forum category.
1351
 *
1352
 * @param int $categoryId the id of the forum category
1353
 * @param int $courseId   Optional. The course ID
1354
 *
1355
 * @return CForumForum[] containing all the information about the forums (regardless of their category)
1356
 *
1357
 * @author Patrick Cool <[email protected]>, Ghent University
1358
 *
1359
 * @version february 2006, dokeos 1.8
1360
 */
1361
function get_forums_in_category($categoryId, $courseId = 0)
1362
{
1363
    $repo = Container::getForumRepository();
1364
    $course = api_get_course_entity($courseId);
1365
1366
    $qb = $repo->getResourcesByCourse($course, null);
1367
    $qb
1368
        ->andWhere('resource.forumCategory = :catId')
1369
        ->setParameter('catId', $categoryId)
1370
        ->orderBy('resource.forumOrder')
1371
    ;
1372
1373
    return $qb->getQuery()->getResult();
1374
}
1375
1376
/**
1377
 * Retrieve all the forums (regardless of their category) or of only one.
1378
 * The forums are sorted according to the forum_order.
1379
 * Since it does not take the forum category into account there probably
1380
 * will be two or more forums that have forum_order=1, ...
1381
 *
1382
 * @param bool $includeGroupsForum
1383
 * @param int  $sessionId
1384
 *
1385
 * @return CForumForum[]
1386
 */
1387
function get_forums(
1388
    $courseId = '',
1389
    $includeGroupsForum = true,
1390
    $sessionId = 0
1391
) {
1392
    $repo = Container::getForumRepository();
1393
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
1394
    $course = api_get_course_entity($courseId);
1395
    $session = api_get_session_entity($sessionId);
1396
1397
    $qb = $repo->getResourcesByCourse($course, $session);
1398
1399
    /*$qb->andWhere('resource.forumCategory = :catId')
1400
        ->setParameter('catId', $cat_id);
1401
    */
1402
    return $qb->getQuery()->getResult();
1403
1404
    $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...
1405
    $course_info = api_get_course_info($course_code);
1406
1407
    $table_forums = Database::get_course_table(TABLE_FORUM);
1408
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1409
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1410
1411
    // Condition for the session
1412
    $session_id = (int) $sessionId ?: api_get_session_id();
1413
    $sessionIdLink = 0 === $session_id ? '' : ' AND threads.session_id = item_properties.session_id';
1414
1415
    $condition_session = api_get_session_condition(
1416
        $session_id,
1417
        true,
1418
        false,
1419
        'item_properties.session_id'
1420
    );
1421
1422
    $course_id = $course_info['real_id'];
1423
1424
    $forum_list = [];
1425
    $includeGroupsForumSelect = '';
1426
    if (!$includeGroupsForum) {
1427
        $includeGroupsForumSelect = ' AND (forum_of_group = 0 OR forum_of_group IS NULL) ';
1428
    }
1429
1430
    $allowToEdit = api_is_allowed_to_edit();
1431
1432
    if (empty($id)) {
1433
        // Student
1434
        // Select all the forum information of all forums (that are visible to students).
1435
        $sql = "SELECT item_properties.*, forum.*
1436
                FROM $table_forums forum
1437
                INNER JOIN $table_item_property item_properties
1438
                ON (
1439
                    forum.forum_id = item_properties.ref AND
1440
                    forum.c_id = item_properties.c_id
1441
                )
1442
                WHERE
1443
                    item_properties.visibility = 1 AND
1444
                    item_properties.tool = '".TOOL_FORUM."'
1445
                    $condition_session AND
1446
                    forum.c_id = $course_id AND
1447
                    item_properties.c_id = $course_id
1448
                    $includeGroupsForumSelect
1449
                ORDER BY forum.forum_order ASC";
1450
1451
        // Select the number of threads of the forums (only the threads that are visible).
1452
        $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1453
                FROM $table_threads threads
1454
                INNER JOIN $table_item_property item_properties
1455
                ON (
1456
                    threads.thread_id = item_properties.ref AND
1457
                    threads.c_id = item_properties.c_id
1458
                    $sessionIdLink
1459
                )
1460
                WHERE
1461
                    item_properties.visibility=1 AND
1462
                    item_properties.tool='".TOOL_FORUM_THREAD."' AND
1463
                    threads.c_id = $course_id AND
1464
                    item_properties.c_id = $course_id
1465
                GROUP BY threads.forum_id";
1466
1467
        // Course Admin
1468
        if ($allowToEdit) {
1469
            // Select all the forum information of all forums (that are not deleted).
1470
            $sql = "SELECT item_properties.*, forum.*
1471
                    FROM $table_forums forum
1472
                    INNER JOIN $table_item_property item_properties
1473
                    ON (
1474
                        forum.forum_id = item_properties.ref AND
1475
                        forum.c_id = item_properties.c_id
1476
                    )
1477
                    WHERE
1478
                        item_properties.visibility <> 2 AND
1479
                        item_properties.tool = '".TOOL_FORUM."'
1480
                        $condition_session AND
1481
                        forum.c_id = $course_id AND
1482
                        item_properties.c_id = $course_id
1483
                        $includeGroupsForumSelect
1484
                    ORDER BY forum_order ASC";
1485
1486
            // Select the number of threads of the forums (only the threads that are not deleted).
1487
            $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1488
                    FROM $table_threads threads
1489
                    INNER JOIN $table_item_property item_properties
1490
                    ON (
1491
                        threads.thread_id = item_properties.ref AND
1492
                        threads.c_id = item_properties.c_id
1493
                        $sessionIdLink
1494
                    )
1495
                    WHERE
1496
                        item_properties.visibility<>2 AND
1497
                        item_properties.tool='".TOOL_FORUM_THREAD."' AND
1498
                        threads.c_id = $course_id AND
1499
                        item_properties.c_id = $course_id
1500
                    GROUP BY threads.forum_id";
1501
        }
1502
    } else {
1503
        // GETTING ONE SPECIFIC FORUM
1504
        /* We could do the splitup into student and course admin also but we want
1505
        to have as much as information about a certain forum as possible
1506
        so we do not take too much information into account. This function
1507
         (or this section of the function) is namely used to fill the forms
1508
        when editing a forum (and for the moment it is the only place where
1509
        we use this part of the function) */
1510
1511
        // Select all the forum information of the given forum (that is not deleted).
1512
        $sql = "SELECT * FROM $table_item_property item_properties
1513
                INNER JOIN $table_forums forum
1514
                ON (forum.forum_id = item_properties.ref AND forum.c_id = item_properties.c_id)
1515
                WHERE
1516
                    forum.forum_id = $id AND
1517
                    forum.c_id = $course_id AND
1518
                    item_properties.visibility != 2 AND
1519
                    item_properties.tool = '".TOOL_FORUM."'
1520
                ORDER BY forum_order ASC";
1521
1522
        // Select the number of threads of the forum.
1523
        $sql2 = "SELECT count(*) AS number_of_threads, forum_id
1524
                FROM $table_threads
1525
                WHERE
1526
                    forum_id = $id
1527
                GROUP BY forum_id";
1528
    }
1529
1530
    // Handling all the forum information.
1531
    $result = Database::query($sql);
1532
    while ($row = Database::fetch_assoc($result)) {
1533
        if (empty($id)) {
1534
            $forum_list[$row['forum_id']] = $row;
1535
        } else {
1536
            $forum_list = $row;
1537
        }
1538
    }
1539
1540
    // Handling the thread count information.
1541
    $result2 = Database::query($sql2);
1542
    while ($row2 = Database::fetch_array($result2)) {
1543
        if (empty($id)) {
1544
            $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
1545
        } else {
1546
            $forum_list['number_of_threads'] = $row2['number_of_threads'];
1547
        }
1548
    }
1549
1550
    /* Finding the last post information
1551
    (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)*/
1552
    if (empty($id)) {
1553
        if (is_array($forum_list)) {
1554
            foreach ($forum_list as $key => $value) {
1555
                $lastPost = get_last_post_information(
1556
                    $key,
1557
                    $allowToEdit,
1558
                    $course_id
1559
                );
1560
1561
                if ($lastPost) {
1562
                    $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
1563
                    $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
1564
                    $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
1565
                    $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
1566
                    $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1567
                    $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1568
                    $forum_list[$key]['last_post_title'] = $lastPost['last_post_title'];
1569
                    $forum_list[$key]['last_post_text'] = $lastPost['last_post_text'];
1570
                }
1571
            }
1572
        } else {
1573
            $forum_list = [];
1574
        }
1575
    } else {
1576
        $lastPost = get_last_post_information(
1577
            $id,
1578
            $allowToEdit,
1579
            $course_id
1580
        );
1581
        if ($lastPost) {
1582
            $forum_list['last_post_id'] = $lastPost['last_post_id'];
1583
            $forum_list['last_poster_id'] = $lastPost['last_poster_id'];
1584
            $forum_list['last_post_date'] = $lastPost['last_post_date'];
1585
            $forum_list['last_poster_name'] = $lastPost['last_poster_name'];
1586
            $forum_list['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1587
            $forum_list['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1588
            $forum_list['last_post_title'] = $lastPost['last_post_title'];
1589
            $forum_list['last_post_text'] = $lastPost['last_post_text'];
1590
        }
1591
    }
1592
1593
    return $forum_list;
1594
}
1595
1596
/**
1597
 * This function gets all the last post information of a certain forum.
1598
 *
1599
 * @param int    $forum_id        the id of the forum we want to know the last post information of
1600
 * @param bool   $show_invisibles
1601
 * @param string $course_id       course db name
1602
 * @param int    $sessionId       Optional. The session id
1603
 *
1604
 * @return array containing all the information about the last post
1605
 *               (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname,
1606
 *               last_poster_firstname)
1607
 *
1608
 * @author Patrick Cool <[email protected]>, Ghent University
1609
 *
1610
 * @version february 2006, dokeos 1.8
1611
 */
1612
function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null, $sessionId = 0)
1613
{
1614
    if (!isset($course_id)) {
1615
        $course_id = api_get_course_int_id();
1616
    } else {
1617
        $course_id = (int) $course_id;
1618
    }
1619
    $sessionId = $sessionId ? (int) $sessionId : api_get_session_id();
1620
1621
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1622
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1623
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1624
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1625
1626
    $forum_id = (int) $forum_id;
1627
    $return_array = [];
1628
1629
    // First get the threads to make sure there is no inconsistency in the
1630
    // database between forum and thread
1631
    $sql = "SELECT iid as thread_id FROM $table_threads
1632
            WHERE
1633
                forum_id = $forum_id AND
1634
                c_id = $course_id AND
1635
                session_id = $sessionId";
1636
    $result = Database::query($sql);
1637
    if (0 == Database::num_rows($result)) {
1638
        // If there are no threads in this forum, then there are no posts
1639
        return [];
1640
    }
1641
    $threads = [];
1642
    while ($row = Database::fetch_row($result)) {
1643
        $threads[] = $row[0];
1644
    }
1645
    $threadsList = implode(',', $threads);
1646
    // Now get the posts that are linked to these threads
1647
    $sql = "SELECT
1648
                post.iid as post_id,
1649
                post.forum_id,
1650
                post.poster_id,
1651
                post.poster_name,
1652
                post.post_date,
1653
                users.lastname,
1654
                users.firstname,
1655
                post.visible,
1656
                thread_properties.visibility AS thread_visibility,
1657
                forum_properties.visibility AS forum_visibility,
1658
                post.post_title,
1659
                post.post_text
1660
            FROM
1661
                $table_posts post,
1662
                $table_users users,
1663
                $table_item_property thread_properties,
1664
                $table_item_property forum_properties
1665
            WHERE
1666
                post.forum_id = $forum_id AND
1667
                post.thread_id IN ($threadsList) AND
1668
                post.poster_id = users.id AND
1669
                 post.thread_id = thread_properties.ref AND thread_properties.tool='".TOOL_FORUM_THREAD."'
1670
                AND post.forum_id=forum_properties.ref
1671
                AND forum_properties.tool='".TOOL_FORUM."'
1672
                AND post.c_id = $course_id AND
1673
                thread_properties.c_id = $course_id AND
1674
                forum_properties.c_id = $course_id
1675
            ORDER BY post.iid DESC";
1676
    $result = Database::query($sql);
1677
1678
    if ($show_invisibles) {
1679
        $row = Database::fetch_array($result);
1680
        $return_array['last_post_id'] = $row['post_id'];
1681
        $return_array['last_poster_id'] = $row['poster_id'];
1682
        $return_array['last_post_date'] = $row['post_date'];
1683
        $return_array['last_poster_name'] = $row['poster_name'];
1684
        $return_array['last_poster_lastname'] = $row['lastname'];
1685
        $return_array['last_poster_firstname'] = $row['firstname'];
1686
        $return_array['last_post_title'] = $row['post_title'];
1687
        $return_array['last_post_text'] = $row['post_text'];
1688
1689
        return $return_array;
1690
    } else {
1691
        // We have to loop through the results to find the first one that is
1692
        // actually visible to students (forum_category, forum, thread AND post are visible).
1693
        while ($row = Database::fetch_array($result)) {
1694
            if ('1' == $row['visible'] && '1' == $row['thread_visibility'] && '1' == $row['forum_visibility']) {
1695
                $return_array['last_post_id'] = $row['post_id'];
1696
                $return_array['last_poster_id'] = $row['poster_id'];
1697
                $return_array['last_post_date'] = $row['post_date'];
1698
                $return_array['last_poster_name'] = $row['poster_name'];
1699
                $return_array['last_poster_lastname'] = $row['lastname'];
1700
                $return_array['last_poster_firstname'] = $row['firstname'];
1701
                $return_array['last_post_title'] = $row['post_title'];
1702
                $return_array['last_post_text'] = $row['post_text'];
1703
1704
                return $return_array;
1705
            }
1706
        }
1707
    }
1708
}
1709
1710
/**
1711
 * Retrieve all the threads of a given forum.
1712
 *
1713
 * @param int|null $courseId  Optional If is null then it is considered the current course
1714
 * @param int|null $sessionId Optional. If is null then it is considered the current session
1715
 *
1716
 * @return CForumThread[]
1717
 */
1718
function get_threads($forumId, $courseId = null, $sessionId = null)
1719
{
1720
    $repo = Container::getForumThreadRepository();
1721
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
1722
    $course = api_get_course_entity($courseId);
1723
    $session = api_get_session_entity($sessionId);
1724
1725
    $qb = $repo->getResourcesByCourse($course, $session);
1726
1727
    $qb->andWhere('resource.forum = :forum')->setParameter('forum', $forumId);
1728
1729
    return $qb->getQuery()->getResult();
1730
1731
    /*$groupId = api_get_group_id();
1732
    $sessionId = null !== $sessionId ? (int) $sessionId : api_get_session_id();
1733
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1734
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1735
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1736
1737
    $courseId = null !== $courseId ? (int) $courseId : api_get_course_int_id();
1738
    $groupInfo = GroupManager::get_group_properties($groupId);
1739
    $groupCondition = '';
1740
1741
    if (!empty($groupInfo)) {
1742
        $groupIid = $groupInfo['iid'];
1743
        $groupCondition = " AND item_properties.to_group_id = '$groupIid' ";
1744
    }
1745
1746
    $sessionCondition = api_get_session_condition(
1747
        $sessionId,
1748
        true,
1749
        false,
1750
        'item_properties.session_id'
1751
    );
1752
1753
    // important note:  it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
1754
    // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
1755
    // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
1756
    // This is why it is added to the end of the field selection
1757
    $sql = "SELECT DISTINCT
1758
                item_properties.*,
1759
                users.firstname,
1760
                users.lastname,
1761
                users.user_id,
1762
                thread.locked as locked,
1763
                thread.*
1764
            FROM $table_threads thread
1765
            INNER JOIN $table_item_property item_properties
1766
            ON
1767
                thread.thread_id = item_properties.ref AND
1768
                item_properties.c_id = thread.c_id AND
1769
                item_properties.tool = '".TABLE_FORUM_THREAD."'
1770
                $groupCondition
1771
                $sessionCondition
1772
            LEFT JOIN $table_users users
1773
                ON thread.thread_poster_id = users.user_id
1774
            WHERE
1775
                item_properties.visibility='1' AND
1776
                thread.forum_id = ".(int) $forum_id." AND
1777
                thread.c_id = $courseId
1778
            ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
1779
1780
    if (api_is_allowed_to_edit()) {
1781
        $sql = "SELECT DISTINCT
1782
                    item_properties.*,
1783
                    users.firstname,
1784
                    users.lastname,
1785
                    users.id as user_id,
1786
                    thread.locked as locked,
1787
                    thread.*
1788
                FROM $table_threads thread
1789
                INNER JOIN $table_item_property item_properties
1790
                ON
1791
                    thread.thread_id = item_properties.ref AND
1792
                    item_properties.c_id = thread.c_id AND
1793
                    item_properties.tool = '".TABLE_FORUM_THREAD."'
1794
                    $groupCondition
1795
                    $sessionCondition
1796
                LEFT JOIN $table_users users
1797
                    ON thread.thread_poster_id=users.user_id
1798
                WHERE
1799
                    item_properties.visibility<>2 AND
1800
                    thread.forum_id = ".(int) $forum_id." AND
1801
                    thread.c_id = $courseId
1802
                ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
1803
    }
1804
    $result = Database::query($sql);
1805
    $list = [];
1806
    $alreadyAdded = [];
1807
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1808
        if (in_array($row['thread_id'], $alreadyAdded)) {
1809
            continue;
1810
        }
1811
        $list[] = $row;
1812
        $alreadyAdded[] = $row['thread_id'];
1813
    }
1814
1815
    return $list;*/
1816
}
1817
1818
/**
1819
 * Get a thread by Id and course id.
1820
 *
1821
 * @param int $threadId the thread Id
1822
 * @param int $cId      the course id
1823
 *
1824
 * @return array containing all the information about the thread
1825
 */
1826
function getThreadInfo($threadId, $cId)
1827
{
1828
    $repo = Database::getManager()->getRepository(CForumThread::class);
1829
    /** @var CForumThread $forumThread */
1830
    $forumThread = $repo->findOneBy(['iid' => $threadId, 'cId' => $cId]);
1831
1832
    $thread = [];
1833
    if ($forumThread) {
1834
        $thread['iid'] = $forumThread->getIid();
1835
        $thread['threadId'] = $forumThread->getIid();
1836
        $thread['threadTitle'] = $forumThread->getThreadTitle();
1837
        $thread['forumId'] = $forumThread->getForum() ? $forumThread->getForum()->getIid() : 0;
1838
        $thread['sessionId'] = $forumThread->getSessionId();
1839
        $thread['threadSticky'] = $forumThread->getThreadSticky();
1840
        $thread['locked'] = $forumThread->getLocked();
1841
        $thread['threadTitleQualify'] = $forumThread->getThreadTitleQualify();
1842
        $thread['threadQualifyMax'] = $forumThread->getThreadQualifyMax();
1843
        $thread['threadCloseDate'] = $forumThread->getThreadCloseDate();
1844
        $thread['threadWeight'] = $forumThread->getThreadWeight();
1845
        $thread['threadPeerQualify'] = $forumThread->isThreadPeerQualify();
1846
    }
1847
1848
    return $thread;
1849
}
1850
1851
/**
1852
 * Retrieve all posts of a given thread.
1853
 *
1854
 * @param int    $threadId       The thread ID
1855
 * @param string $orderDirection Optional. The direction for sort the posts
1856
 * @param bool   $recursive      Optional. If the list is recursive
1857
 * @param int    $postId         Optional. The post ID for recursive list
1858
 * @param int    $depth          Optional. The depth to indicate the indent
1859
 *
1860
 * @todo move to a repository
1861
 *
1862
 * @return array containing all the information about the posts of a given thread
1863
 */
1864
function getPosts(
1865
    CForumForum $forum,
1866
    $threadId,
1867
    $orderDirection = 'ASC',
1868
    $recursive = false,
1869
    $postId = null,
1870
    $depth = -1
1871
) {
1872
    $em = Database::getManager();
1873
1874
    if (api_is_allowed_to_edit(false, true)) {
1875
        $visibleCriteria = Criteria::expr()->neq('visible', 2);
1876
    } else {
1877
        $visibleCriteria = Criteria::expr()->eq('visible', 1);
1878
    }
1879
1880
    $criteria = Criteria::create();
1881
    $criteria
1882
        ->where(Criteria::expr()->eq('thread', $threadId))
1883
        ->andWhere(Criteria::expr()->eq('cId', $forum->getCId()))
1884
        ->andWhere($visibleCriteria)
1885
    ;
1886
1887
    $groupId = api_get_group_id();
1888
    $filterModerated = true;
1889
1890
    if (empty($groupId)) {
1891
        if (api_is_allowed_to_edit()) {
1892
            $filterModerated = false;
1893
        }
1894
    } else {
1895
        $groupEntity = api_get_group_entity($groupId);
1896
        if (GroupManager::isTutorOfGroup(api_get_user_id(), $groupEntity) ||
1897
            api_is_allowed_to_edit(false, true)
1898
        ) {
1899
            $filterModerated = false;
1900
        }
1901
    }
1902
1903
    if ($recursive) {
1904
        $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
1905
    }
1906
1907
    $qb = $em->getRepository(CForumPost::class)->createQueryBuilder('p');
1908
    $qb->select('p')
1909
        ->addCriteria($criteria)
1910
        ->addOrderBy('p.iid', $orderDirection);
1911
1912
    if ($filterModerated && 1 == $forum->isModerated()) {
1913
        if (!api_is_allowed_to_edit(false, true)) {
1914
            $userId = api_get_user_id();
1915
            $qb->andWhere(
1916
                'p.status = 1 OR
1917
                    (p.status = '.CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
1918
                    (p.status = ".CForumPost::STATUS_REJECTED." AND p.posterId = $userId) OR
1919
                    (p.status IS NULL AND p.posterId = $userId)
1920
                    "
1921
            );
1922
        }
1923
    }
1924
1925
    $posts = $qb->getQuery()->getResult();
1926
    $depth++;
1927
1928
    $list = [];
1929
    /** @var CForumPost $post */
1930
    foreach ($posts as $post) {
1931
        $postInfo = [
1932
            'iid' => $post->getIid(),
1933
            'c_id' => $post->getCId(),
1934
            'post_id' => $post->getIid(),
1935
            'post_title' => $post->getPostTitle(),
1936
            'post_text' => $post->getPostText(),
1937
            'thread_id' => $post->getThread() ? $post->getThread()->getIid() : 0,
1938
            'forum_id' => $post->getForum()->getIid(),
1939
            //'poster_id' => $post->getPosterId(),
1940
            //'poster_name' => $post->getPosterName(),
1941
            'post_date' => $post->getPostDate(),
1942
            'post_notification' => $post->getPostNotification(),
1943
            'post_parent_id' => $post->getPostParentId(),
1944
            'visible' => $post->getVisible(),
1945
            'status' => $post->getStatus(),
1946
            'indent_cnt' => $depth,
1947
            'entity' => $post,
1948
        ];
1949
1950
        /*$posterId = $post->getPosterId();
1951
        if (!empty($posterId)) {
1952
            $user = api_get_user_entity($posterId);
1953
            if ($user) {
1954
                $postInfo['user_id'] = $user->getId();
1955
                $postInfo['username'] = $user->getUsername();
1956
                $postInfo['username_canonical'] = $user->getUsernameCanonical();
1957
                $postInfo['lastname'] = $user->getLastname();
1958
                $postInfo['firstname'] = $user->getFirstname();
1959
                $postInfo['complete_name'] = UserManager::formatUserFullName($user);
1960
            }
1961
        }*/
1962
1963
        $list[] = $postInfo;
1964
1965
        if (!$recursive) {
1966
            continue;
1967
        }
1968
        $list = array_merge(
1969
            $list,
1970
            getPosts(
1971
                $forum,
1972
                $threadId,
1973
                $orderDirection,
1974
                $recursive,
1975
                $post->getIid(),
1976
                $depth
1977
            )
1978
        );
1979
    }
1980
1981
    return $list;
1982
}
1983
1984
/**
1985
 * This function retrieves forum thread users details.
1986
 *
1987
 * @param int $thread_id Thread ID
1988
 * @param   string  Course DB name (optional)
1989
 *
1990
 * @return Doctrine\DBAL\Driver\Statement|null array Array of type
1991
 *                                             ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
1992
 *
1993
 * @author Christian Fasanando <[email protected]>,
1994
 *
1995
 * @todo     this function need to be improved
1996
 *
1997
 * @version octubre 2008, dokeos 1.8
1998
 */
1999
function get_thread_users_details($thread_id)
2000
{
2001
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2002
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2003
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2004
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2005
2006
    $course_id = api_get_course_int_id();
2007
2008
    $is_western_name_order = api_is_western_name_order();
2009
    if ($is_western_name_order) {
2010
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2011
    } else {
2012
        $orderby = 'ORDER BY user.lastname, user.firstname';
2013
    }
2014
2015
    if (api_get_session_id()) {
2016
        $session_info = api_get_session_info(api_get_session_id());
2017
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2018
        //not showing coaches
2019
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2020
                FROM $t_posts p, $t_users user, $t_session_rel_user session_rel_user_rel_course
2021
                WHERE
2022
                    p.poster_id = user.id AND
2023
                    user.id = session_rel_user_rel_course.user_id AND
2024
                    session_rel_user_rel_course.status<>'2' AND
2025
                    session_rel_user_rel_course.user_id NOT IN ($user_to_avoid) AND
2026
                    p.thread_id = ".(int) $thread_id.' AND
2027
                    session_id = '.api_get_session_id()." AND
2028
                    p.c_id = $course_id AND
2029
                    session_rel_user_rel_course.c_id = ".$course_id." $orderby ";
2030
    } else {
2031
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2032
                FROM $t_posts p, $t_users user, $t_course_user course_user
2033
                WHERE
2034
                    p.poster_id = user.id
2035
                    AND user.id = course_user.user_id
2036
                    AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH.'
2037
                    AND p.thread_id = '.(int) $thread_id."
2038
                    AND course_user.status NOT IN('1') AND
2039
                    p.c_id = $course_id AND
2040
                    course_user.c_id = ".$course_id." $orderby";
2041
    }
2042
2043
    return Database::query($sql);
2044
}
2045
2046
/**
2047
 * This function retrieves forum thread users qualify.
2048
 *
2049
 * @param int $thread_id Thread ID
2050
 * @param   string  Course DB name (optional)
2051
 *
2052
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2053
 *
2054
 * @author Jhon Hinojosa
2055
 *
2056
 * @todo     this function need to be improved
2057
 */
2058
function get_thread_users_qualify($thread_id)
2059
{
2060
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2061
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2062
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2063
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2064
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2065
2066
    $course_id = api_get_course_int_id();
2067
    $sessionId = api_get_session_id();
2068
2069
    $is_western_name_order = api_is_western_name_order();
2070
    if ($is_western_name_order) {
2071
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2072
    } else {
2073
        $orderby = 'ORDER BY user.lastname, user.firstname';
2074
    }
2075
2076
    if ($sessionId) {
2077
        $session_info = api_get_session_info($sessionId);
2078
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2079
        //not showing coaches
2080
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2081
                FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
2082
                WHERE poster_id = user.id
2083
                    AND post.poster_id = qualify.user_id
2084
                    AND user.id = scu.user_id
2085
                    AND scu.status<>'2'
2086
                    AND scu.user_id NOT IN ($user_to_avoid)
2087
                    AND qualify.thread_id = ".(int) $thread_id.'
2088
                    AND post.thread_id = '.(int) $thread_id."
2089
                    AND scu.session_id = $sessionId
2090
                    AND scu.c_id = ".$course_id." AND
2091
                    qualify.c_id = $course_id AND
2092
                    post.c_id = $course_id
2093
                $orderby ";
2094
    } else {
2095
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2096
                FROM $t_posts post,
2097
                     $t_qualify qualify,
2098
                     $t_users user,
2099
                     $t_course_user course_user
2100
                WHERE
2101
                     post.poster_id = user.id
2102
                     AND post.poster_id = qualify.user_id
2103
                     AND user.id = course_user.user_id
2104
                     AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH.'
2105
                     AND qualify.thread_id = '.(int) $thread_id.'
2106
                     AND post.thread_id = '.(int) $thread_id."
2107
                     AND course_user.status not in('1')
2108
                     AND course_user.c_id = $course_id
2109
                     AND qualify.c_id = $course_id
2110
                     AND post.c_id = $course_id
2111
                 $orderby ";
2112
    }
2113
2114
    return Database::query($sql);
2115
}
2116
2117
/**
2118
 * This function retrieves forum thread users not qualify.
2119
 *
2120
 * @param int $thread_id Thread ID
2121
 * @param   string  Course DB name (optional)
2122
 *
2123
 * @return Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2124
 *
2125
 * @author   Jhon Hinojosa<[email protected]>,
2126
 *
2127
 * @version oct 2008, dokeos 1.8
2128
 */
2129
function get_thread_users_not_qualify($thread_id)
2130
{
2131
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2132
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2133
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2134
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2135
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2136
2137
    $is_western_name_order = api_is_western_name_order();
2138
    if ($is_western_name_order) {
2139
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2140
    } else {
2141
        $orderby = 'ORDER BY user.lastname, user.firstname';
2142
    }
2143
2144
    $course_id = api_get_course_int_id();
2145
2146
    $sql1 = "SELECT user_id FROM  $t_qualify
2147
             WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
2148
    $result1 = Database::query($sql1);
2149
    $cad = '';
2150
    while ($row = Database::fetch_array($result1)) {
2151
        $cad .= $row['user_id'].',';
2152
    }
2153
    if ('' == $cad) {
2154
        $cad = '0';
2155
    } else {
2156
        $cad = substr($cad, 0, strlen($cad) - 1);
2157
    }
2158
2159
    if (api_get_session_id()) {
2160
        $session_info = api_get_session_info(api_get_session_id());
2161
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2162
        //not showing coaches
2163
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2164
                FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
2165
                WHERE poster_id = user.id
2166
                    AND user.id NOT IN (".$cad.")
2167
                    AND user.id = session_rel_user_rel_course.user_id
2168
                    AND session_rel_user_rel_course.status<>'2'
2169
                    AND session_rel_user_rel_course.user_id NOT IN ($user_to_avoid)
2170
                    AND post.thread_id = ".(int) $thread_id.'
2171
                    AND session_id = '.api_get_session_id()."
2172
                    AND session_rel_user_rel_course.c_id = $course_id AND post.c_id = $course_id $orderby ";
2173
    } else {
2174
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2175
                FROM $t_posts post, $t_users user,$t_course_user course_user
2176
                WHERE post.poster_id = user.id
2177
                AND user.id NOT IN (".$cad.')
2178
                AND user.id = course_user.user_id
2179
                AND course_user.relation_type<>'.COURSE_RELATION_TYPE_RRHH.'
2180
                AND post.thread_id = '.(int) $thread_id."
2181
                AND course_user.status not in('1')
2182
                AND course_user.c_id = $course_id AND post.c_id = $course_id  $orderby";
2183
    }
2184
2185
    return Database::query($sql);
2186
}
2187
2188
/**
2189
 * This function retrieves all the information of a given forumcategory id.
2190
 *
2191
 * @param int $cat_id that indicates the forum
2192
 *
2193
 * @return array returns if there are category or bool returns if there aren't category
2194
 *
2195
 * @author Patrick Cool <[email protected]>, Ghent University
2196
 *
2197
 * @version february 2006, dokeos 1.8
2198
 */
2199
function get_forumcategory_information($cat_id)
2200
{
2201
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
2202
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2203
2204
    $course_id = api_get_course_int_id();
2205
    $sql = "SELECT *
2206
            FROM $table_categories forumcategories
2207
            INNER JOIN $table_item_property item_properties
2208
            ON (forumcategories.c_id = item_properties.c_id)
2209
            WHERE
2210
                forumcategories.c_id = $course_id AND
2211
                item_properties.c_id = $course_id AND
2212
                item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
2213
                item_properties.ref='".Database::escape_string($cat_id)."' AND
2214
                forumcategories.cat_id='".Database::escape_string($cat_id)."'";
2215
    $result = Database::query($sql);
2216
2217
    return Database::fetch_array($result);
2218
}
2219
2220
/**
2221
 * This function counts the number of forums inside a given category.
2222
 *
2223
 * @param int $cat_id the id of the forum category
2224
 *
2225
 * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return
2226
 *       the number of visible forums, $countinvisible=1 would return the number of visible and invisible forums
2227
 *
2228
 * @return int the number of forums inside the given category
2229
 *
2230
 * @author Patrick Cool <[email protected]>, Ghent University
2231
 *
2232
 * @version february 2006, dokeos 1.8
2233
 */
2234
function count_number_of_forums_in_category($cat_id)
2235
{
2236
    $table_forums = Database::get_course_table(TABLE_FORUM);
2237
    $course_id = api_get_course_int_id();
2238
    $cat_id = (int) $cat_id;
2239
    $sql = "SELECT count(*) AS number_of_forums
2240
            FROM $table_forums
2241
            WHERE c_id = $course_id AND forum_category = $cat_id";
2242
    $result = Database::query($sql);
2243
    $row = Database::fetch_array($result);
2244
2245
    return $row['number_of_forums'];
2246
}
2247
2248
/**
2249
 * This function update a thread.
2250
 *
2251
 * @param array $values - The form Values
2252
 */
2253
function updateThread($values)
2254
{
2255
    if (!api_is_allowed_to_edit()) {
2256
        return '';
2257
    }
2258
2259
    $logInfo = [
2260
        'tool' => TOOL_FORUM,
2261
        'tool_id' => $values['forum_id'],
2262
        'tool_id_detail' => $values['thread_id'],
2263
        'action' => 'edit-thread',
2264
        'action_details' => 'thread',
2265
        'info' => $values['thread_title'],
2266
    ];
2267
    Event::registerLog($logInfo);
2268
2269
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
2270
    $courseId = api_get_course_int_id();
2271
    $courseCode = api_get_course_id();
2272
    $sessionId = api_get_session_id();
2273
2274
    // Simple update + set gradebook values to null
2275
    $params = [
2276
        'thread_title' => $values['thread_title'],
2277
        'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
2278
    ];
2279
    $where = ['c_id = ? AND iid = ?' => [$courseId, $values['thread_id']]];
2280
    Database::update($threadTable, $params, $where);
2281
2282
    $id = $values['thread_id'];
2283
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
2284
        $courseCode,
2285
        LINK_FORUM_THREAD,
2286
        $id,
2287
        $sessionId
2288
    );
2289
2290
    $gradebookLink = null;
2291
    $em = Database::getManager();
2292
    if (!empty($linkInfo) && isset($linkInfo['id'])) {
2293
        $gradebookLink = $em->getRepository(GradebookLink::class)->find($linkInfo['id']);
2294
    }
2295
2296
    // values 1 or 0
2297
    $check = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : false;
2298
    if ($check) {
2299
        $title = Security::remove_XSS(stripslashes($values['calification_notebook_title']));
2300
        $value = isset($values['numeric_calification']) ? (int) ($values['numeric_calification']) : 0;
2301
        $weight = isset($values['weight_calification']) ? (float) ($values['weight_calification']) : 0;
2302
        $description = '';
2303
        // Update title
2304
        $params = [
2305
            'thread_title_qualify' => $values['calification_notebook_title'],
2306
            'thread_qualify_max' => api_float_val($values['numeric_calification']),
2307
            'thread_weight' => api_float_val($values['weight_calification']),
2308
            'thread_peer_qualify' => $values['thread_peer_qualify'],
2309
        ];
2310
        $where = ['c_id = ? AND iid = ?' => [$courseId, $values['thread_id']]];
2311
        Database::update($threadTable, $params, $where);
2312
2313
        if (!$linkInfo) {
2314
            GradebookUtils::add_resource_to_course_gradebook(
2315
                $values['category_id'],
2316
                $courseCode,
2317
                LINK_FORUM_THREAD,
2318
                $id,
2319
                $title,
2320
                $weight,
2321
                $value,
2322
                $description,
2323
                1,
2324
                $sessionId
2325
            );
2326
        } else {
2327
            if ($gradebookLink) {
2328
                $gradebookLink->setWeight($weight);
2329
                $em->persist($gradebookLink);
2330
                $em->flush();
2331
            }
2332
        }
2333
    } else {
2334
        $params = [
2335
            'thread_title_qualify' => '',
2336
            'thread_qualify_max' => 0,
2337
            'thread_weight' => 0,
2338
            'thread_peer_qualify' => 0,
2339
        ];
2340
        $where = ['c_id = ? AND iid = ?' => [$courseId, $values['thread_id']]];
2341
        Database::update($threadTable, $params, $where);
2342
2343
        if (!empty($linkInfo)) {
2344
            if ($gradebookLink) {
2345
                $em->remove($gradebookLink);
2346
                $em->flush();
2347
            }
2348
        }
2349
    }
2350
2351
    $message = get_lang('The post has been modified').'<br />';
2352
    Display::addFlash(Display::return_message($message, 'confirmation', false));
2353
}
2354
2355
function saveThread(
2356
    CForumForum $forum,
2357
    array $values,
2358
    array $courseInfo = [],
2359
    $showMessage = true,
2360
    $userId = 0,
2361
    $sessionId = 0
2362
): ?CForumThread {
2363
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
2364
    $userId = $userId ?: api_get_user_id();
2365
    $course_id = $courseInfo['real_id'];
2366
    $courseCode = $courseInfo['code'];
2367
    $sessionId = $sessionId ?: api_get_session_id();
2368
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2369
2370
    $post_date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
2371
    $visible = 1;
2372
    if ('1' == $forum->getApprovalDirectPost() && !api_is_allowed_to_edit(null, true)) {
2373
        $visible = 0; // The post has not been approved yet.
2374
    }
2375
    $clean_post_title = $values['post_title'];
2376
2377
    $user = api_get_user_entity(api_get_user_id());
2378
    $course = api_get_course_entity($course_id);
2379
    $session = api_get_session_entity($sessionId);
2380
2381
    // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
2382
    $thread = new CForumThread();
2383
    $thread
2384
        ->setCId($course_id)
2385
        ->setThreadTitle($clean_post_title)
2386
        ->setForum($forum)
2387
        ->setUser($user)
2388
        ->setThreadDate($post_date)
2389
        ->setThreadSticky($values['thread_sticky'] ?? 0)
2390
        ->setThreadTitleQualify($values['calification_notebook_title'] ?? '')
2391
        ->setThreadQualifyMax($values['numeric_calification'] ?? 0)
2392
        ->setThreadWeight($values['weight_calification'] ?? 0)
2393
        ->setThreadPeerQualify(isset($values['thread_peer_qualify']) ? (bool) $values['thread_peer_qualify'] : false)
2394
        ->setSessionId($sessionId)
2395
        ->setLpItemId(isset($values['lp_item_id']) ? (int) $values['lp_item_id'] : 0)
2396
        ->setParent($forum)
2397
        ->addCourseLink($course, $session)
2398
    ;
2399
2400
    $repo = Container::getForumThreadRepository();
2401
    $repo->create($thread);
2402
2403
    if (!$thread->getIid()) {
2404
        return null;
2405
    }
2406
2407
    // Add option gradebook qualify.
2408
    if (isset($values['thread_qualify_gradebook']) &&
2409
        1 == $values['thread_qualify_gradebook']
2410
    ) {
2411
        // Add function gradebook.
2412
        $resourcename = stripslashes($values['calification_notebook_title']);
2413
        GradebookUtils::add_resource_to_course_gradebook(
2414
            $values['category_id'],
2415
            $courseCode,
2416
            5,
2417
            $thread->getIid(),
2418
            $resourcename,
2419
            $values['weight_calification'],
2420
            $values['numeric_calification'],
2421
            '',
2422
            0,
2423
            $sessionId
2424
        );
2425
    }
2426
2427
    /*api_item_property_update(
2428
        $courseInfo,
2429
        TOOL_FORUM_THREAD,
2430
        $thread->getIid(),
2431
        'ForumThreadAdded',
2432
        $userId,
2433
        $groupInfo,
2434
        null,
2435
        null,
2436
        null,
2437
        $sessionId
2438
    );*/
2439
2440
    // If the forum properties tell that the posts have to be approved
2441
    // we have to put the whole thread invisible,
2442
    // because otherwise the students will see the thread and not the post
2443
    // in the thread.
2444
    // We also have to change $visible because the post itself has to be
2445
    // visible in this case (otherwise the teacher would have
2446
    // to make the thread visible AND the post.
2447
    // Default behaviour
2448
    /*api_set_default_visibility(
2449
        $thread->getIid(),
2450
        TOOL_FORUM_THREAD,
2451
        $groupId,
2452
        $courseInfo,
2453
        $sessionId,
2454
        $userId
2455
    );*/
2456
2457
    if (0 == $visible) {
2458
        /*api_item_property_update(
2459
            $courseInfo,
2460
            TOOL_FORUM_THREAD,
2461
            $thread->getIid(),
2462
            'invisible',
2463
            $userId,
2464
            $groupInfo
2465
        );*/
2466
        $visible = 1;
2467
    }
2468
2469
    $logInfo = [
2470
        'tool' => TOOL_FORUM,
2471
        'tool_id' => $values['forum_id'],
2472
        'tool_id_detail' => $thread->getIid(),
2473
        'action' => 'new-thread',
2474
        'info' => $clean_post_title,
2475
    ];
2476
    Event::registerLog($logInfo);
2477
2478
    // We now store the content in the table_post table.
2479
    $post = new CForumPost();
2480
    $post
2481
        ->setCId($course_id)
2482
        ->setPostTitle($clean_post_title)
2483
        ->setPostText($values['post_text'])
2484
        ->setThread($thread)
2485
        ->setForum($forum)
2486
        ->setUser(api_get_user_entity($userId))
2487
        //->setPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2488
        ->setPostDate($post_date)
2489
        ->setPostNotification(isset($values['post_notification']) ? (int) $values['post_notification'] : null)
2490
        ->setVisible($visible)
2491
        ->setStatus(CForumPost::STATUS_VALIDATED)
2492
        ->setParent($thread)
2493
        ->addCourseLink($course, $session)
2494
    ;
2495
2496
    if ($forum->isModerated()) {
2497
        $post->setStatus(
2498
            api_is_course_admin() ? CForumPost::STATUS_VALIDATED : CForumPost::STATUS_WAITING_MODERATION
2499
        );
2500
    }
2501
2502
    $repo = Container::getForumPostRepository();
2503
    $repo->create($post);
2504
    $thread->setThreadLastPost($post);
2505
    $em = Database::getManager();
2506
    $em->persist($thread);
2507
    $em->flush();
2508
2509
    $postId = $post->getIid();
2510
2511
    $logInfo = [
2512
        'tool' => TOOL_FORUM,
2513
        'tool_id' => $values['forum_id'],
2514
        'tool_id_detail' => $thread->getIid(),
2515
        'action' => 'new-post',
2516
        'info' => $clean_post_title,
2517
    ];
2518
    Event::registerLog($logInfo);
2519
2520
    // Now we have to update the thread table to fill the thread_last_post
2521
    // field (so that we know when the thread has been updated for the last time).
2522
    $sql = "UPDATE $table_threads
2523
            SET thread_last_post = '".$postId."'
2524
            WHERE
2525
                c_id = $course_id AND
2526
                iid = '".$thread->getIid()."'";
2527
    Database::query($sql);
2528
    $message = get_lang('The new thread has been added');
2529
2530
    // Overwrite default message.
2531
    if ($forum->isModerated() &&
2532
        !api_is_allowed_to_edit(null, true)
2533
    ) {
2534
        $message = get_lang('Your message has to be approved before people can view it.');
2535
    }
2536
2537
    add_forum_attachment_file(
2538
        null,
2539
        $post
2540
    );
2541
2542
    if ('1' == $forum->getApprovalDirectPost() &&
2543
        !api_is_allowed_to_edit(null, true)
2544
    ) {
2545
        $message .= get_lang('Your message has to be approved before people can view it.').'<br />';
2546
        $message .= get_lang('You can now return to the').
2547
            ' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
2548
            get_lang('Forum').'</a><br />';
2549
    } else {
2550
        $message .= get_lang('You can now return to the').
2551
            ' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
2552
            get_lang('Forum').'</a><br />';
2553
        $message .= get_lang('You can now return to the').
2554
            ' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&thread='.$thread->getIid().'">'.
2555
            get_lang('Message').'</a>';
2556
    }
2557
    $reply_info['new_post_id'] = $postId;
2558
    $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
2559
2560
    if (1 == $my_post_notification) {
2561
        set_notification('thread', $thread->getIid(), true);
2562
    }
2563
2564
    send_notification_mails(
2565
        $forum,
2566
        $thread,
2567
        $reply_info,
2568
        $courseInfo['code']
2569
    );
2570
2571
    Session::erase('formelements');
2572
    Session::erase('origin');
2573
    Session::erase('breadcrumbs');
2574
    Session::erase('addedresource');
2575
    Session::erase('addedresourceid');
2576
2577
    if ($showMessage) {
2578
        Display::addFlash(Display::return_message($message, 'success', false));
2579
    }
2580
2581
    return $thread;
2582
}
2583
2584
/**
2585
 * This function displays the form that is used to add a post. This can be a new thread or a reply.
2586
 *
2587
 * @param string $action
2588
 *                            is the parameter that determines if we are
2589
 *                            2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete
2590
 *                            thread (if enabled)
2591
 *                            3. replymessage: Replying to a message ($action =replymessage) => I-frame with the
2592
 *                            complete thread (if enabled)
2593
 *                            (I first thought to put and I-frame with the message only)
2594
 *                            4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread
2595
 *                            (if enabled). The message will be in the reply. (I first thought not to put an I-frame
2596
 *                            here)
2597
 * @param array  $form_values
2598
 * @param bool   $showPreview
2599
 *
2600
 * @return FormValidator
2601
 */
2602
function show_add_post_form(CForumForum $forum, CForumThread $thread, CForumPost $post = null, $action, $form_values, $showPreview = true)
2603
{
2604
    $_user = api_get_user_info();
2605
    $action = isset($action) ? Security::remove_XSS($action) : '';
2606
    $threadId = $thread->getIid();
2607
    $forumId = $forum->getIid();
2608
    $giveRevision = isset($_GET['give_revision']) && 1 == $_GET['give_revision'];
2609
    $postId = $post ? $post->getIid() : 0;
2610
2611
    $url = api_get_self().'?'.http_build_query(
2612
        [
2613
            'action' => $action,
2614
            'forum' => $forumId,
2615
            'thread' => $threadId,
2616
            'post' => $postId,
2617
        ]
2618
    ).'&'.api_get_cidreq();
2619
2620
    $form = new FormValidator(
2621
        'thread',
2622
        'post',
2623
        $url
2624
    );
2625
    $form->setConstants(['forum' => '5']);
2626
2627
    // Setting the form elements.
2628
    $form->addElement('hidden', 'forum_id', $forumId);
2629
    $form->addElement('hidden', 'thread_id', $threadId);
2630
    $form->addElement('hidden', 'action', $action);
2631
2632
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
2633
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
2634
        $form->addElement('text', 'poster_name', get_lang('Name'));
2635
        $form->applyFilter('poster_name', 'html_filter');
2636
    }
2637
2638
    $form->addElement('text', 'post_title', get_lang('Title'));
2639
    $form->addHtmlEditor(
2640
        'post_text',
2641
        get_lang('Text'),
2642
        true,
2643
        false,
2644
        api_is_allowed_to_edit(null, true) ? [
2645
            'ToolbarSet' => 'Forum',
2646
            'Width' => '100%',
2647
            'Height' => '300',
2648
        ] : [
2649
            'ToolbarSet' => 'ForumStudent',
2650
            'Width' => '100%',
2651
            'Height' => '300',
2652
            'UserStatus' => 'student',
2653
        ]
2654
    );
2655
    $form->addRule('post_text', get_lang('Required field'), 'required');
2656
2657
    if (in_array($action, ['replythread', 'replymessage', 'quote'])) {
2658
        $extraFields = new ExtraField('forum_post');
2659
        $extraFields->addElements(
2660
            $form,
2661
            null,
2662
            [], //exclude
2663
            false, // filter
2664
            false, // tag as select
2665
            ['ask_for_revision'], //show only fields
2666
            [], // order fields
2667
            [] // extra data);
2668
        );
2669
    }
2670
2671
    $iframe = null;
2672
    if ($showPreview) {
2673
        if ('newthread' !== $action && !empty($threadId)) {
2674
            $iframe = '<iframe style="border: 1px solid black"
2675
            src="iframe_thread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$threadId.'#'.$postId.'" width="100%"></iframe>';
2676
        }
2677
        if (!empty($iframe)) {
2678
            $form->addElement('label', get_lang('Thread'), $iframe);
2679
        }
2680
    }
2681
2682
    if (in_array($action, ['quote', 'replymessage'])) {
2683
        $form->addFile('user_upload[]', get_lang('Attachment'));
2684
        $form->addButton(
2685
            'add_attachment',
2686
            get_lang('Add attachment'),
2687
            'paperclip',
2688
            'default',
2689
            'default',
2690
            null,
2691
            ['id' => 'reply-add-attachment']
2692
        );
2693
    } else {
2694
        $form->addFile('user_upload', get_lang('Attachment'));
2695
    }
2696
2697
    if ($giveRevision) {
2698
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
2699
        $form->addHidden('give_revision', 1);
2700
        if (false === $hide) {
2701
            $extraField = new ExtraField('forum_post');
2702
            $extraField->addElements(
2703
                $form,
2704
                null,
2705
                [], //exclude
2706
                false, // filter
2707
                false, // tag as select
2708
                ['revision_language'], //show only fields
2709
                [], // order fields
2710
                [] // extra data
2711
            );
2712
        } else {
2713
            $form->addHidden('extra_revision_language', 1);
2714
        }
2715
    }
2716
2717
    // Setting the class and text of the form title and submit button.
2718
    if ('quote' === $action) {
2719
        $form->addButtonCreate(get_lang('Quote this message'), 'SubmitPost');
2720
    } elseif ('replythread' === $action) {
2721
        $form->addButtonCreate(get_lang('Reply to this thread'), 'SubmitPost');
2722
    } elseif ('replymessage' === $action) {
2723
        $form->addButtonCreate(get_lang('Reply to this message'), 'SubmitPost');
2724
    }
2725
2726
    $defaults['thread_peer_qualify'] = 0;
2727
    if (!empty($form_values)) {
2728
        $defaults['post_title'] = prepare4display($form_values['post_title']);
2729
        $defaults['post_text'] = prepare4display($form_values['post_text']);
2730
        $defaults['post_notification'] = (int) $form_values['post_notification'];
2731
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
2732
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
2733
    }
2734
2735
    // If we are quoting a message we have to retrieve the information of the post we are quoting so that
2736
    // we can add this as default to the textarea.
2737
    // We also need to put the parent_id of the post in a hidden form when
2738
    if (('quote' === $action || 'replymessage' === $action || $giveRevision) && !empty($postId)) {
2739
        // we are quoting or replying to a message (<> reply to a thread !!!)
2740
        $form->addHidden('post_parent_id', $post->getIid());
2741
        // If we are replying or are quoting then we display a default title.
2742
        $posterName = UserManager::formatUserFullName($post->getUser());
2743
        $defaults['post_title'] = get_lang('Re:').api_html_entity_decode($post->getPostTitle(), ENT_QUOTES);
2744
        // When we are quoting a message then we have to put that message into the wysiwyg editor.
2745
        // Note: The style has to be hardcoded here because using class="quote" didn't work.
2746
        if ('quote' === $action) {
2747
            $defaults['post_text'] = '<div>&nbsp;</div>
2748
                <div style="margin: 5px;">
2749
                    <div style="font-size: 90%; font-style: italic;">'.
2750
                get_lang('Quoting').' '.$posterName.':</div>
2751
                        <div style="color: #006600; font-size: 90%;  font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.
2752
                prepare4display($post->getPostText()).'
2753
                        </div>
2754
                    </div>
2755
                <div>&nbsp;</div>
2756
                <div>&nbsp;</div>
2757
            ';
2758
        }
2759
        if ($giveRevision) {
2760
            $defaults['post_text'] = prepare4display($post->getPostText());
2761
        }
2762
    }
2763
2764
    $form->setDefaults(isset($defaults) ? $defaults : []);
2765
2766
    // The course admin can make a thread sticky (=appears with special icon and always on top).
2767
    $form->addRule('post_title', get_lang('Required field'), 'required');
2768
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
2769
        $form->addRule(
2770
            'poster_name',
2771
            get_lang('Required field'),
2772
            'required'
2773
        );
2774
    }
2775
2776
    // Validation or display
2777
    if ($form->validate()) {
2778
        $check = Security::check_token('post');
2779
        if ($check) {
2780
            $values = $form->getSubmitValues();
2781
            if (isset($values['thread_qualify_gradebook']) &&
2782
                '1' == $values['thread_qualify_gradebook'] &&
2783
                empty($values['weight_calification'])
2784
            ) {
2785
                Display::addFlash(
2786
                    Display::return_message(
2787
                        get_lang('You must assign a score to this activity').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
2788
                        'error',
2789
                        false
2790
                    )
2791
                );
2792
2793
                return false;
2794
            }
2795
2796
            $postId = 0;
2797
            $threadId = 0;
2798
2799
            switch ($action) {
2800
                case 'quote':
2801
                case 'replythread':
2802
                case 'replymessage':
2803
                    $postId = store_reply($forum, $thread, $values);
2804
2805
                    break;
2806
            }
2807
2808
            if ($postId) {
2809
                if (isset($values['give_revision']) && 1 == $values['give_revision']) {
2810
                    $extraFieldValues = new ExtraFieldValue('forum_post');
2811
                    $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
2812
                    $params = [
2813
                        'item_id' => $postId,
2814
                        'extra_revision_language' => $revisionLanguage,
2815
                    ];
2816
2817
                    $extraFieldValues->saveFieldValues(
2818
                        $params,
2819
                        false,
2820
                        false,
2821
                        ['revision_language']
2822
                    );
2823
                }
2824
2825
                if (in_array($action, ['replythread', 'replymessage', 'quote'])) {
2826
                    $extraFieldValues = new ExtraFieldValue('forum_post');
2827
                    $params = [
2828
                        'item_id' => $postId,
2829
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
2830
                    ];
2831
                    $extraFieldValues->saveFieldValues(
2832
                        $params,
2833
                        false,
2834
                        false,
2835
                        ['ask_for_revision']
2836
                    );
2837
                }
2838
            }
2839
2840
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
2841
                [
2842
                    'forum' => $forumId,
2843
                    'thread' => $thread->getIid(),
2844
                ]
2845
            );
2846
2847
            Security::clear_token();
2848
            header('Location: '.$url);
2849
            exit;
2850
        }
2851
    } else {
2852
        $token = Security::get_token();
2853
        $form->addElement('hidden', 'sec_token');
2854
        $form->setConstants(['sec_token' => $token]);
2855
2856
        // Delete from $_SESSION forum attachment from other posts
2857
        // and keep only attachments for new post
2858
        clearAttachedFiles(FORUM_NEW_POST);
2859
        // Get forum attachment ajax table to add it to form
2860
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $forum->getIid());
2861
        $ajaxHtml = $attachmentAjaxTable;
2862
        $form->addElement('html', $ajaxHtml);
2863
2864
        return $form;
2865
    }
2866
}
2867
2868
function newThread(CForumForum $forum, $form_values = '', $showPreview = true)
2869
{
2870
    $_user = api_get_user_info();
2871
    $forumId = $forum->getIid();
2872
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
2873
    $giveRevision = isset($_GET['give_revision']) && 1 == $_GET['give_revision'];
2874
    $action = 'new_thread';
2875
2876
    $url = api_get_self().'?'.http_build_query(
2877
            [
2878
                'action' => $action,
2879
                'forum' => $forumId,
2880
                'post' => $my_post,
2881
            ]
2882
        ).'&'.api_get_cidreq();
2883
2884
    $form = new FormValidator(
2885
        'thread',
2886
        'post',
2887
        $url
2888
    );
2889
2890
    // Setting the form elements.
2891
    $form->addElement('hidden', 'forum_id', $forumId);
2892
    $form->addElement('hidden', 'thread_id', 0);
2893
    $form->addElement('hidden', 'action', $action);
2894
2895
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
2896
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
2897
        $form->addElement('text', 'poster_name', get_lang('Name'));
2898
        $form->applyFilter('poster_name', 'html_filter');
2899
    }
2900
2901
    $form->addElement('text', 'post_title', get_lang('Title'));
2902
    $form->addHtmlEditor(
2903
        'post_text',
2904
        get_lang('Text'),
2905
        true,
2906
        false,
2907
        api_is_allowed_to_edit(null, true) ? [
2908
            'ToolbarSet' => 'Forum',
2909
            'Width' => '100%',
2910
            'Height' => '300',
2911
        ] : [
2912
            'ToolbarSet' => 'ForumStudent',
2913
            'Width' => '100%',
2914
            'Height' => '300',
2915
            'UserStatus' => 'student',
2916
        ]
2917
    );
2918
    $form->addRule('post_text', get_lang('Required field'), 'required');
2919
2920
    $extraFields = new ExtraField('forum_post');
2921
    $extraFields->addElements(
2922
        $form,
2923
        null,
2924
        [], //exclude
2925
        false, // filter
2926
        false, // tag as select
2927
        ['ask_for_revision'], //show only fields
2928
        [], // order fields
2929
        [] // extra data);
2930
    );
2931
2932
    if (Gradebook::is_active() &&
2933
        (api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor())
2934
    ) {
2935
        $form->addElement('advanced_settings', 'advanced_params', get_lang('Advanced settings'));
2936
        $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
2937
2938
        // Thread qualify
2939
        if (Gradebook::is_active()) {
2940
            //Loading gradebook select
2941
            GradebookUtils::load_gradebook_select_in_tool($form);
2942
            $form->addElement(
2943
                'checkbox',
2944
                'thread_qualify_gradebook',
2945
                '',
2946
                get_lang('Grade this thread'),
2947
                'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
2948
            );
2949
        } else {
2950
            $form->addElement('hidden', 'thread_qualify_gradebook', false);
2951
        }
2952
2953
        $form->addElement('html', '<div id="options_field" style="display:none">');
2954
        $form->addElement('text', 'numeric_calification', get_lang('Maximum score'));
2955
        $form->applyFilter('numeric_calification', 'html_filter');
2956
        $form->addElement('text', 'calification_notebook_title', get_lang('Column header in Competences Report'));
2957
        $form->applyFilter('calification_notebook_title', 'html_filter');
2958
2959
        $form->addElement(
2960
            'text',
2961
            'weight_calification',
2962
            get_lang('Weight in Report'),
2963
            ['value' => '0.00', 'onfocus' => 'javascript: this.select();']
2964
        );
2965
        $form->applyFilter('weight_calification', 'html_filter');
2966
2967
        $group = [];
2968
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
2969
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
2970
        $form->addGroup(
2971
            $group,
2972
            '',
2973
            [
2974
                get_lang('Thread scored by peers'),
2975
                get_lang('Thread scored by peersComment'),
2976
            ]
2977
        );
2978
        $form->addElement('html', '</div>');
2979
        $form->addElement('html', '</div>');
2980
    }
2981
2982
    Skill::addSkillsToForm($form, ITEM_TYPE_FORUM_THREAD, 0);
2983
    $form->addElement('checkbox', 'thread_sticky', '', get_lang('This is a sticky message (appears always on top and has a special sticky icon)'));
2984
2985
    $form->addFile('user_upload', get_lang('Attachment'));
2986
2987
    if ($giveRevision) {
2988
        $hide = api_get_configuration_value('hide_forum_post_revision_language');
2989
        $form->addHidden('give_revision', 1);
2990
        if (false === $hide) {
2991
            $extraField = new ExtraField('forum_post');
2992
            $extraField->addElements(
2993
                $form,
2994
                null,
2995
                [], //exclude
2996
                false, // filter
2997
                false, // tag as select
2998
                ['revision_language'], //show only fields
2999
                [], // order fields
3000
                [] // extra data
3001
            );
3002
        } else {
3003
            $form->addHidden('extra_revision_language', 1);
3004
        }
3005
    }
3006
    $form->addButtonCreate(get_lang('Create thread'), 'SubmitPost');
3007
3008
    $defaults['thread_peer_qualify'] = 0;
3009
    if (!empty($form_values)) {
3010
        $defaults['post_title'] = prepare4display($form_values['post_title']);
3011
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3012
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3013
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3014
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3015
    }
3016
3017
    $form->setDefaults(isset($defaults) ? $defaults : []);
3018
3019
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3020
    $form->addRule('post_title', get_lang('Required field'), 'required');
3021
    if (1 == $forum->getAllowAnonymous() && !isset($_user['user_id'])) {
3022
        $form->addRule(
3023
            'poster_name',
3024
            get_lang('Required field'),
3025
            'required'
3026
        );
3027
    }
3028
3029
    // Validation or display
3030
    if ($form->validate()) {
3031
        $check = Security::check_token('post');
3032
        if ($check) {
3033
            $values = $form->getSubmitValues();
3034
            if (isset($values['thread_qualify_gradebook']) &&
3035
                '1' == $values['thread_qualify_gradebook'] &&
3036
                empty($values['weight_calification'])
3037
            ) {
3038
                Display::addFlash(
3039
                    Display::return_message(
3040
                        get_lang('You must assign a score to this activity').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3041
                        'error',
3042
                        false
3043
                    )
3044
                );
3045
3046
                return false;
3047
            }
3048
3049
            $newThread = saveThread($forum, $values);
3050
            if ($newThread) {
3051
                Skill::saveSkills($form, ITEM_TYPE_FORUM_THREAD, $newThread->getIid());
3052
                $postId = $newThread->getThreadLastPost();
3053
3054
                if ($postId) {
3055
                    if (isset($values['give_revision']) && 1 == $values['give_revision']) {
3056
                        $extraFieldValues = new ExtraFieldValue('forum_post');
3057
                        $revisionLanguage = isset($values['extra_revision_language']) ? $values['extra_revision_language'] : '';
3058
3059
                        $params = [
3060
                            'item_id' => $postId,
3061
                            'extra_revision_language' => $revisionLanguage,
3062
                        ];
3063
3064
                        $extraFieldValues->saveFieldValues(
3065
                            $params,
3066
                            false,
3067
                            false,
3068
                            ['revision_language']
3069
                        );
3070
                    }
3071
                    $extraFieldValues = new ExtraFieldValue('forum_post');
3072
                    $params = [
3073
                        'item_id' => $postId,
3074
                        'extra_ask_for_revision' => isset($values['extra_ask_for_revision']) ? $values['extra_ask_for_revision'] : '',
3075
                    ];
3076
                    $extraFieldValues->saveFieldValues(
3077
                        $params,
3078
                        false,
3079
                        false,
3080
                        ['ask_for_revision']
3081
                    );
3082
                }
3083
            }
3084
3085
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3086
                [
3087
                    'forum' => $forumId,
3088
                    'thread' => $newThread->getIid(),
3089
                ]
3090
            );
3091
3092
            Security::clear_token();
3093
            header('Location: '.$url);
3094
            exit;
3095
        }
3096
    } else {
3097
        $token = Security::get_token();
3098
        $form->addElement('hidden', 'sec_token');
3099
        $form->setConstants(['sec_token' => $token]);
3100
3101
        // Delete from $_SESSION forum attachment from other posts
3102
        // and keep only attachments for new post
3103
        clearAttachedFiles(FORUM_NEW_POST);
3104
        // Get forum attachment ajax table to add it to form
3105
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $forum->getIid());
3106
        $ajaxHtml = $attachmentAjaxTable;
3107
        $form->addElement('html', $ajaxHtml);
3108
3109
        return $form;
3110
    }
3111
}
3112
3113
/**
3114
 * @param CForumThread $threadInfo
3115
 * @param int          $user_id
3116
 * @param int          $thread_id
3117
 * @param int          $thread_qualify
3118
 * @param int          $qualify_time
3119
 * @param int          $session_id
3120
 *
3121
 * @return array optional
3122
 *
3123
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3124
 *
3125
 * @version October 2008, dokeos  1.8.6
3126
 */
3127
function saveThreadScore(
3128
    CForumThread $threadEntity,
3129
    $user_id,
3130
    $thread_id,
3131
    $thread_qualify = 0,
3132
    $qualify_time,
3133
    $session_id = 0
3134
) {
3135
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3136
3137
    $course_id = api_get_course_int_id();
3138
    $session_id = (int) $session_id;
3139
    $currentUserId = api_get_user_id();
3140
3141
    if ($user_id == (string) ((int) $user_id) &&
3142
        $thread_id == (string) ((int) $thread_id) &&
3143
        $thread_qualify == (string) ((float) $thread_qualify)
3144
    ) {
3145
        $max = $threadEntity->getThreadQualifyMax();
3146
        if ($thread_qualify <= $max) {
3147
            if ($threadEntity->isThreadPeerQualify()) {
3148
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3149
                        WHERE
3150
                            c_id = $course_id AND
3151
                            user_id = $user_id AND
3152
                            qualify_user_id = $currentUserId AND
3153
                            thread_id = ".$thread_id;
3154
            } else {
3155
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3156
                        WHERE
3157
                            c_id = $course_id AND
3158
                            user_id = $user_id AND
3159
                            thread_id = ".$thread_id;
3160
            }
3161
3162
            $result = Database::query($sql);
3163
            $row = Database::fetch_array($result);
3164
3165
            if (0 == $row[0]) {
3166
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3167
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3168
                Database::query($sql);
3169
3170
                return 'insert';
3171
            } else {
3172
                saveThreadScoreHistory(
3173
                    '1',
3174
                    $course_id,
3175
                    $user_id,
3176
                    $thread_id
3177
                );
3178
3179
                // Update
3180
                $sql = "UPDATE $table_threads_qualify
3181
                        SET
3182
                            qualify = '".$thread_qualify."',
3183
                            qualify_time = '".$qualify_time."'
3184
                        WHERE
3185
                            c_id = $course_id AND
3186
                            user_id=".$user_id.' AND
3187
                            thread_id='.$thread_id." AND
3188
                            qualify_user_id = $currentUserId
3189
                        ";
3190
                Database::query($sql);
3191
3192
                return 'update';
3193
            }
3194
        } else {
3195
            return null;
3196
        }
3197
    }
3198
}
3199
3200
/**
3201
 * This function shows qualify.
3202
 *
3203
 * @param string $option    contains the information of option to run
3204
 * @param int    $user_id   contains the information the current user id
3205
 * @param int    $thread_id contains the information the current thread id
3206
 *
3207
 * @return int qualify
3208
 *             <code> $option=1 obtained the qualification of the current thread</code>
3209
 *
3210
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3211
 *
3212
 * @version October 2008, dokeos  1.8.6
3213
 */
3214
function showQualify($option, $user_id, $thread_id)
3215
{
3216
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3217
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3218
3219
    $course_id = api_get_course_int_id();
3220
    $user_id = (int) $user_id;
3221
    $thread_id = (int) $thread_id;
3222
3223
    if (empty($user_id) || empty($thread_id)) {
3224
        return 0;
3225
    }
3226
3227
    $sql = '';
3228
    switch ($option) {
3229
        case 1:
3230
            $sql = "SELECT qualify FROM $table_threads_qualify
3231
                    WHERE
3232
                        c_id = $course_id AND
3233
                        user_id=".$user_id.' AND
3234
                        thread_id='.$thread_id;
3235
3236
            break;
3237
        case 2:
3238
            $sql = "SELECT thread_qualify_max FROM $table_threads
3239
                    WHERE c_id = $course_id AND iid=".$thread_id;
3240
3241
            break;
3242
    }
3243
3244
    if (!empty($sql)) {
3245
        $rs = Database::query($sql);
3246
        $row = Database::fetch_array($rs);
3247
        if ($row) {
3248
            return $row[0];
3249
        }
3250
    }
3251
3252
    return 0;
3253
}
3254
3255
/**
3256
 * This function gets qualify historical.
3257
 *
3258
 * @param int  $user_id   contains the information the current user id
3259
 * @param int  $thread_id contains the information the current thread id
3260
 * @param bool $opt       contains the information of option to run
3261
 *
3262
 * @return array
3263
 *
3264
 * @author Christian Fasanando <[email protected]>,
3265
 * @author Isaac Flores <[email protected]>,
3266
 *
3267
 * @version October 2008, dokeos  1.8.6
3268
 */
3269
function getThreadScoreHistory($user_id, $thread_id, $opt)
3270
{
3271
    $user_id = (int) $user_id;
3272
    $thread_id = (int) $thread_id;
3273
3274
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3275
    $course_id = api_get_course_int_id();
3276
3277
    if ('false' == $opt) {
3278
        $sql = "SELECT * FROM $table_threads_qualify_log
3279
                WHERE
3280
                    c_id = $course_id AND
3281
                    thread_id='".$thread_id."' AND
3282
                    user_id='".$user_id."'
3283
                ORDER BY qualify_time";
3284
    } else {
3285
        $sql = "SELECT * FROM $table_threads_qualify_log
3286
                WHERE
3287
                    c_id = $course_id AND
3288
                    thread_id='".$thread_id."' AND
3289
                    user_id='".$user_id."'
3290
                ORDER BY qualify_time DESC";
3291
    }
3292
    $rs = Database::query($sql);
3293
    $log = [];
3294
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3295
        $log[] = $row;
3296
    }
3297
3298
    return $log;
3299
}
3300
3301
/**
3302
 * This function stores qualify historical.
3303
 *
3304
 * @param bool contains the information of option to run
3305
 * @param string contains the information the current course id
3306
 * @param int contains the information the current forum id
3307
 * @param int contains the information the current user id
3308
 * @param int contains the information the current thread id
3309
 * @param int contains the information the current qualify
3310
 * @param string $option
3311
 * @param int    $course_id
3312
 * @param int    $user_id
3313
 * @param int    $thread_id
3314
 *
3315
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3316
 *
3317
 * @version October 2008, dokeos  1.8.6
3318
 */
3319
function saveThreadScoreHistory(
3320
    $option,
3321
    $course_id,
3322
    $user_id,
3323
    $thread_id
3324
) {
3325
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3326
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3327
3328
    $course_id = (int) $course_id;
3329
    $qualify_user_id = api_get_user_id();
3330
3331
    if ($user_id == (string) ((int) $user_id) &&
3332
        $thread_id == (string) ((int) $thread_id) && 1 == $option
3333
    ) {
3334
        // Extract information of thread_qualify.
3335
        $sql = "SELECT qualify, qualify_time
3336
                FROM $table_threads_qualify
3337
                WHERE
3338
                    c_id = $course_id AND
3339
                    user_id = ".$user_id.' AND
3340
                    thread_id = '.$thread_id." AND
3341
                    qualify_user_id = $qualify_user_id
3342
                ";
3343
        $rs = Database::query($sql);
3344
        $row = Database::fetch_array($rs);
3345
3346
        // Insert thread_historical.
3347
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3348
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3349
        Database::query($sql);
3350
    }
3351
}
3352
3353
/**
3354
 * This function shows current thread qualify .
3355
 *
3356
 * @param int $threadId
3357
 * @param int $sessionId
3358
 * @param int $userId
3359
 *
3360
 * @return array or null if is empty
3361
 *
3362
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3363
 *
3364
 * @version December 2008, dokeos  1.8.6
3365
 */
3366
function current_qualify_of_thread($threadId, $sessionId, $userId)
3367
{
3368
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3369
3370
    $course_id = api_get_course_int_id();
3371
    $currentUserId = api_get_user_id();
3372
    $sessionId = (int) $sessionId;
3373
    $threadId = (int) $threadId;
3374
3375
    $sql = "SELECT qualify FROM $table_threads_qualify
3376
            WHERE
3377
                c_id = $course_id AND
3378
                thread_id = $threadId AND
3379
                session_id = $sessionId AND
3380
                qualify_user_id = $currentUserId AND
3381
                user_id = $userId
3382
            ";
3383
    $res = Database::query($sql);
3384
    $row = Database::fetch_array($res, 'ASSOC');
3385
3386
    if ($row) {
3387
        return $row['qualify'];
3388
    }
3389
3390
    return 0;
3391
}
3392
3393
/**
3394
 * This function stores a reply in the forum_post table.
3395
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date).
3396
 *
3397
 * @param array $values
3398
 * @param int   $courseId Optional
3399
 * @param int   $userId   Optional
3400
 *
3401
 * @return int post id
3402
 */
3403
function store_reply(CForumForum $forum, CForumThread $thread, $values, $courseId = 0, $userId = 0)
3404
{
3405
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
3406
    $_course = api_get_course_info_by_id($courseId);
3407
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3408
    $post_date = api_get_utc_datetime();
3409
    $userId = $userId ?: api_get_user_id();
3410
3411
    if (1 == $forum->getAllowAnonymous()) {
3412
        if (api_is_anonymous() && empty($userId)) {
3413
            $userId = api_get_anonymous_id();
3414
        }
3415
    }
3416
3417
    if (empty($userId)) {
3418
        return false;
3419
    }
3420
3421
    $visible = 1;
3422
    if ('1' == $forum->getApprovalDirectPost() &&
3423
        !api_is_allowed_to_edit(null, true)
3424
    ) {
3425
        $visible = 0;
3426
    }
3427
3428
    $upload_ok = 1;
3429
    $new_post_id = 0;
3430
3431
    if ($upload_ok) {
3432
        $course = api_get_course_entity($courseId);
3433
        $session = api_get_session_entity();
3434
3435
        $post = new CForumPost();
3436
        $post
3437
            ->setCId($courseId)
3438
            ->setPostTitle($values['post_title'])
3439
            ->setPostText(isset($values['post_text']) ?: null)
3440
            ->setThread($thread)
3441
            ->setForum($forum)
3442
            ->setUser(api_get_user_entity($userId))
3443
            ->setPostNotification(isset($values['post_notification']) ? $values['post_notification'] : null)
3444
            ->setPostParentId(isset($values['post_parent_id']) ? $values['post_parent_id'] : null)
3445
            ->setVisible($visible)
3446
            ->setPostDate(api_get_utc_datetime(null, false, true))
3447
            ->setParent($thread)
3448
            ->addCourseLink($course, $session)
3449
        ;
3450
3451
        $repo = Container::getForumPostRepository();
3452
        $repo->create($post);
3453
3454
        $new_post_id = $post->getIid();
3455
        if ($new_post_id) {
3456
            $values['new_post_id'] = $new_post_id;
3457
            $message = get_lang('The reply has been added');
3458
3459
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3460
                foreach ($_POST['file_ids'] as $key => $id) {
3461
                    editAttachedFile(
3462
                        [
3463
                            'comment' => $_POST['file_comments'][$key],
3464
                            'post_id' => $new_post_id,
3465
                        ],
3466
                        $id
3467
                    );
3468
                }
3469
            }
3470
3471
            // Update the thread.
3472
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
3473
3474
            // Update the forum.
3475
            /*api_item_property_update(
3476
                $_course,
3477
                TOOL_FORUM,
3478
                $values['forum_id'],
3479
                'NewMessageInForum',
3480
                $userId
3481
            );
3482
3483
            // Insert post
3484
            api_item_property_update(
3485
                $_course,
3486
                TOOL_FORUM_POST,
3487
                $new_post_id,
3488
                'NewPost',
3489
                $userId
3490
            );*/
3491
3492
            if ('1' == $forum->getApprovalDirectPost() &&
3493
                !api_is_allowed_to_edit(null, true)
3494
            ) {
3495
                $message .= '<br />'.get_lang('Your message has to be approved before people can view it.').'<br />';
3496
            }
3497
3498
            if ($forum->isModerated() &&
3499
                !api_is_allowed_to_edit(null, true)
3500
            ) {
3501
                $message .= '<br />'.get_lang('Your message has to be approved before people can view it.').'<br />';
3502
            }
3503
3504
            // Setting the notification correctly.
3505
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3506
            if (1 == $my_post_notification) {
3507
                set_notification('thread', $values['thread_id'], true);
3508
            }
3509
3510
            send_notification_mails(
3511
                $forum,
3512
                $thread,
3513
                $values
3514
            );
3515
            add_forum_attachment_file('', $post);
3516
3517
            $logInfo = [
3518
                'tool' => TOOL_FORUM,
3519
                'tool_id' => $values['forum_id'],
3520
                'tool_id_detail' => $values['thread_id'],
3521
                'action' => 'new-post',
3522
                'action_details' => $values['action'],
3523
                'info' => $values['post_title'],
3524
            ];
3525
            Event::registerLog($logInfo);
3526
        }
3527
3528
        Session::erase('formelements');
3529
        Session::erase('origin');
3530
        Session::erase('breadcrumbs');
3531
        Session::erase('addedresource');
3532
        Session::erase('addedresourceid');
3533
3534
        Display::addFlash(Display::return_message($message, 'confirmation', false));
3535
    } else {
3536
        Display::addFlash(
3537
            Display::return_message(
3538
                get_lang('No file was uploaded.').' '.get_lang('Please select a file before pressing the upload button.'),
3539
                'error'
3540
            )
3541
        );
3542
    }
3543
3544
    return $new_post_id;
3545
}
3546
3547
/**
3548
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
3549
 *
3550
 * @param CForumPost   $post        contains all the information about the current post
3551
 * @param CForumThread $thread      contains all the information about the current thread
3552
 * @param CForumForum  $forum       contains all info about the current forum (to check if attachments are allowed)
3553
 * @param array        $form_values contains the default values to fill the form
3554
 *
3555
 * @author Patrick Cool <[email protected]>, Ghent University
3556
 *
3557
 * @version february 2006, dokeos 1.8
3558
 */
3559
function show_edit_post_form(
3560
    $post,
3561
    $thread,
3562
    $forum,
3563
    $form_values,
3564
    $id_attach = 0
3565
) {
3566
    // Initialize the object.
3567
    $form = new FormValidator(
3568
        'edit_post',
3569
        'post',
3570
        api_get_self().'?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&thread='.(int) ($_GET['thread']).'&post='.(int) ($_GET['post'])
3571
    );
3572
    $form->addElement('header', get_lang('Edit a post'));
3573
    // Setting the form elements.
3574
    $form->addElement('hidden', 'post_id', $post->getIid());
3575
    $form->addElement('hidden', 'thread_id', $thread->getIid());
3576
    $form->addElement('hidden', 'id_attach', $id_attach);
3577
3578
    if (empty($post->getPostParentId())) {
3579
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
3580
    }
3581
3582
    $form->addElement('text', 'post_title', get_lang('Title'));
3583
    $form->applyFilter('post_title', 'html_filter');
3584
    $form->addElement(
3585
        'html_editor',
3586
        'post_text',
3587
        get_lang('Text'),
3588
        null,
3589
        api_is_allowed_to_edit(null, true) ? [
3590
            'ToolbarSet' => 'Forum',
3591
            'Width' => '100%',
3592
            'Height' => '400',
3593
        ] : [
3594
            'ToolbarSet' => 'ForumStudent',
3595
            'Width' => '100%',
3596
            'Height' => '400',
3597
            'UserStatus' => 'student',
3598
        ]
3599
    );
3600
    $form->addRule('post_text', get_lang('Required field'), 'required');
3601
3602
    $extraFields = new ExtraField('forum_post');
3603
    $extraFields->addElements($form, $post->getIid());
3604
3605
    $form->addButtonAdvancedSettings('advanced_params');
3606
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
3607
3608
    if ($forum->isModerated() && api_is_allowed_to_edit(null, true)) {
3609
        $group = [];
3610
        $group[] = $form->createElement(
3611
            'radio',
3612
            'status',
3613
            null,
3614
            get_lang('Validated'),
3615
            1
3616
        );
3617
        $group[] = $form->createElement(
3618
            'radio',
3619
            'status',
3620
            null,
3621
            get_lang('Waiting for moderation'),
3622
            2
3623
        );
3624
        $group[] = $form->createElement(
3625
            'radio',
3626
            'status',
3627
            null,
3628
            get_lang('Rejected'),
3629
            3
3630
        );
3631
        $form->addGroup($group, 'status', get_lang('Status'));
3632
    }
3633
3634
    $defaults['status']['status'] = $post->getStatus();
3635
3636
    $form->addElement(
3637
        'checkbox',
3638
        'post_notification',
3639
        '',
3640
        get_lang('Notify me by e-mail when somebody replies')
3641
    );
3642
3643
    if (api_is_allowed_to_edit(null, true) &&
3644
        empty($post->getPostParentId())
3645
    ) {
3646
        // The sticky checkbox only appears when it is the first post of a thread.
3647
        $form->addElement(
3648
            'checkbox',
3649
            'thread_sticky',
3650
            '',
3651
            get_lang('This is a sticky message (appears always on top and has a special sticky icon)')
3652
        );
3653
        if (1 == $thread->getThreadSticky()) {
3654
            $defaults['thread_sticky'] = true;
3655
        }
3656
    }
3657
3658
    $form->addElement('html', '</div>');
3659
3660
    $form->addFile('user_upload[]', get_lang('Attachment'));
3661
    $form->addButton(
3662
        'add_attachment',
3663
        get_lang('Add attachment'),
3664
        'paperclip',
3665
        'default',
3666
        'default',
3667
        null,
3668
        ['id' => 'reply-add-attachment']
3669
    );
3670
3671
    $form->addButtonUpdate(get_lang('Edit'), 'SubmitPost');
3672
3673
    // Setting the default values for the form elements.
3674
    $defaults['post_title'] = $post->getPostTitle();
3675
    $defaults['post_text'] = $post->getPostText();
3676
3677
    if (1 == $post->getPostNotification()) {
3678
        $defaults['post_notification'] = true;
3679
    }
3680
3681
    if (!empty($form_values)) {
3682
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
3683
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
3684
    }
3685
3686
    $form->setDefaults($defaults);
3687
3688
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3689
    $form->addRule('post_title', get_lang('Required field'), 'required');
3690
3691
    // Validation or display
3692
    if ($form->validate()) {
3693
        $values = $form->exportValues();
3694
        $values['item_id'] = $post->getIid();
3695
        $extraFieldValues = new ExtraFieldValue('forum_post');
3696
        $extraFieldValues->saveFieldValues($values);
3697
3698
        store_edit_post($forum, $values);
3699
    } else {
3700
        // Delete from $_SESSION forum attachment from other posts
3701
        clearAttachedFiles($post->getIid());
3702
        // Get forum attachment ajax table to add it to form
3703
        $fileData = getAttachmentsAjaxTable($post->getIid(), $forum->getIid());
3704
        $form->addElement('html', $fileData);
3705
        $form->display();
3706
    }
3707
}
3708
3709
/**
3710
 * This function stores the edit of a post in the forum_post table.
3711
 *
3712
 * @author Patrick Cool <[email protected]>, Ghent University
3713
 *
3714
 * @version february 2006, dokeos 1.8
3715
 */
3716
function store_edit_post(CForumForum $forum, $values)
3717
{
3718
    $logInfo = [
3719
        'tool' => TOOL_FORUM,
3720
        'tool_id' => $_GET['forum'],
3721
        'tool_id_detail' => $values['thread_id'],
3722
        'action' => 'edit-post',
3723
        'action_details' => 'post',
3724
        'info' => $values['post_title'],
3725
    ];
3726
    Event::registerLog($logInfo);
3727
3728
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
3729
    $course_id = api_get_course_int_id();
3730
3731
    //check if this post is the first of the thread
3732
    // First we check if the change affects the thread and if so we commit
3733
    // the changes (sticky and post_title=thread_title are relevant).
3734
    $posts = getPosts($forum, $values['thread_id']);
3735
    $first_post = null;
3736
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
3737
        $first_post = $posts[0];
3738
    }
3739
3740
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
3741
        // Simple edit
3742
        $params = [
3743
            'thread_title' => $values['post_title'],
3744
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
3745
        ];
3746
        $where = ['iid = ?' => [$values['thread_id']]];
3747
        Database::update($threadTable, $params, $where);
3748
    }
3749
3750
    $status = '';
3751
    $updateStatus = false;
3752
    if ($forum->isModerated()) {
3753
        if (api_is_allowed_to_edit(null, true)) {
3754
            $status = $values['status']['status'];
3755
            $updateStatus = true;
3756
        } else {
3757
            $status = CForumPost::STATUS_WAITING_MODERATION;
3758
            $updateStatus = true;
3759
        }
3760
    }
3761
3762
    $postId = $values['post_id'];
3763
    $repo = Container::getForumPostRepository();
3764
    /** @var CForumPost $post */
3765
    $post = $repo->find($postId);
3766
    if ($post) {
3767
        $post
3768
            ->setPostTitle($values['post_title'])
3769
            ->setPostText($values['post_text'])
3770
            ->setPostNotification(isset($values['post_notification']) ? 1 : 0)
3771
        ;
3772
3773
        if ($updateStatus) {
3774
            $post->setStatus($status);
3775
        }
3776
        $repo->update($post);
3777
    }
3778
3779
    // Update attached files
3780
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3781
        foreach ($_POST['file_ids'] as $key => $id) {
3782
            editAttachedFile(
3783
                [
3784
                    'comment' => $_POST['file_comments'][$key],
3785
                    'post_id' => $values['post_id'],
3786
                ],
3787
                $id
3788
            );
3789
        }
3790
    }
3791
3792
    if (!empty($values['remove_attach'])) {
3793
        throw new Exception('remove_attach');
3794
        //delete_attachment($post->getIid());
3795
    }
3796
3797
    if (empty($values['id_attach'])) {
3798
        add_forum_attachment_file(
3799
            isset($values['file_comment']) ? $values['file_comment'] : null,
3800
            $post
3801
        );
3802
    } else {
3803
        /*edit_forum_attachment_file(
3804
            isset($values['file_comment']) ? $values['file_comment'] : null,
3805
            $values['post_id'],
3806
            $values['id_attach']
3807
        );*/
3808
    }
3809
3810
    $message = get_lang('The post has been modified').'<br />';
3811
    $message .= get_lang('You can now return to the').
3812
        ' <a href="viewforum.php?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&">'.
3813
        get_lang('Forum').'</a><br />';
3814
    $message .= get_lang('You can now return to the').
3815
        ' <a
3816
            href="viewthread.php?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&thread='.$values['thread_id'].'&post='.Security::remove_XSS($_GET['post']).'">'.
3817
        get_lang('Message').'</a>';
3818
3819
    Session::erase('formelements');
3820
    Session::erase('origin');
3821
    Session::erase('breadcrumbs');
3822
    Session::erase('addedresource');
3823
    Session::erase('addedresourceid');
3824
3825
    echo Display::return_message($message, 'confirmation', false);
3826
}
3827
3828
function displayUserLink(User $user)
3829
{
3830
    return '<a href="'.$user->getProfileUrl().'">'.
3831
        Security::remove_XSS(UserManager::formatUserFullName($user)).'</a>';
3832
}
3833
3834
function displayUserImage(User $user)
3835
{
3836
    $url = Container::getIllustrationRepository()->getIllustrationUrl($user, '', ICON_SIZE_BIG);
3837
3838
    return '<div class="thumbnail"><img src="'.$url.'?w=100"/></div>';
3839
}
3840
3841
/**
3842
 * The thread view counter gets increased every time someone looks at the thread.
3843
 *
3844
 * @param int $thread_id
3845
 *
3846
 * @author Patrick Cool <[email protected]>, Ghent University
3847
 *
3848
 * @version february 2006, dokeos 1.8
3849
 */
3850
function increase_thread_view($thread_id)
3851
{
3852
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3853
    $course_id = api_get_course_int_id();
3854
3855
    $sql = "UPDATE $table_threads
3856
            SET thread_views = thread_views + 1
3857
            WHERE
3858
                c_id = $course_id AND
3859
                iid = '".(int) $thread_id."'";
3860
    Database::query($sql);
3861
}
3862
3863
/**
3864
 * The relies counter gets increased every time somebody replies to the thread.
3865
 *
3866
 * @author Patrick Cool <[email protected]>, Ghent University
3867
 *
3868
 * @version february 2006, dokeos 1.8
3869
 *
3870
 * @param int    $threadId
3871
 * @param string $lastPostId
3872
 * @param string $post_date
3873
 */
3874
function updateThreadInfo($threadId, $lastPostId, $post_date)
3875
{
3876
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3877
    $course_id = api_get_course_int_id();
3878
    $sql = "UPDATE $table_threads SET
3879
            thread_replies = thread_replies+1,
3880
            thread_last_post = '".Database::escape_string($lastPostId)."',
3881
            thread_date = '".Database::escape_string($post_date)."'
3882
            WHERE
3883
                c_id = $course_id AND
3884
                iid ='".Database::escape_string($threadId)."'"; // this needs to be cleaned first
3885
    Database::query($sql);
3886
}
3887
3888
/**
3889
 * This function is used to find all the information about what's new in the forum tool.
3890
 *
3891
 * @author Patrick Cool <[email protected]>, Ghent University
3892
 *
3893
 * @version february 2006, dokeos 1.8
3894
 */
3895
function get_whats_new()
3896
{
3897
    $userId = api_get_user_id();
3898
    $course_id = api_get_course_int_id();
3899
3900
    if (empty($course_id) || empty($userId)) {
3901
        return false;
3902
    }
3903
3904
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3905
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
3906
3907
    $tool = TOOL_FORUM;
3908
    $lastForumAccess = Session::read('last_forum_access');
3909
3910
    if (!$lastForumAccess) {
3911
        $sql = "SELECT * FROM $tracking_last_tool_access
3912
                WHERE
3913
                    access_user_id = $userId AND
3914
                    c_id = $course_id AND
3915
                    access_tool = '".Database::escape_string($tool)."'";
3916
        $result = Database::query($sql);
3917
        $row = Database::fetch_array($result);
3918
        if ($row) {
3919
            Session::write('last_forum_access', $row['access_date']);
3920
            $lastForumAccess = $row['access_date'];
3921
        }
3922
    }
3923
3924
    $whatsNew = Session::read('whatsnew_post_info');
3925
3926
    if (!$whatsNew) {
3927
        if ('' != $lastForumAccess) {
3928
            $postInfo = [];
3929
            $sql = "SELECT * FROM $table_posts
3930
                    WHERE
3931
                        c_id = $course_id AND
3932
                        visible = 1 AND
3933
                        post_date > '".Database::escape_string($lastForumAccess)."'";
3934
            $result = Database::query($sql);
3935
            while ($row = Database::fetch_array($result)) {
3936
                $postInfo[$row['forum_id']][$row['thread_id']][$row['iid']] = $row['post_date'];
3937
            }
3938
            Session::write('whatsnew_post_info', $postInfo);
3939
        }
3940
    }
3941
}
3942
3943
function approvePost(CForumPost $post, $action)
3944
{
3945
    if ('invisible' === $action) {
3946
        $visibility = 0;
3947
    }
3948
3949
    if ('visible' === $action) {
3950
        $visibility = 1;
3951
        handle_mail_cue('post', $post->getIid());
3952
    }
3953
3954
    $post->setVisible($visibility);
3955
    Database::getManager()->persist($post);
3956
    Database::getManager()->flush();
3957
3958
    Display::addFlash(Display::return_message(get_lang('The visibility has been changed')));
3959
}
3960
3961
/**
3962
 * This function retrieves all the unapproved messages for a given forum
3963
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see
3964
 * this).
3965
 *
3966
 * @param int $forum_id forum where we want to know the unapproved messages of
3967
 *
3968
 * @return array returns
3969
 *
3970
 * @author Patrick Cool <[email protected]>, Ghent University
3971
 *
3972
 * @version february 2006, dokeos 1.8
3973
 */
3974
function get_unaproved_messages($forum_id)
3975
{
3976
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3977
    $course_id = api_get_course_int_id();
3978
3979
    $return_array = [];
3980
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
3981
            WHERE
3982
                c_id = $course_id AND
3983
                forum_id='".Database::escape_string($forum_id)."' AND
3984
                visible='0' ";
3985
    $result = Database::query($sql);
3986
    while ($row = Database::fetch_array($result)) {
3987
        $return_array[] = $row['thread_id'];
3988
    }
3989
3990
    return $return_array;
3991
}
3992
3993
/**
3994
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
3995
 * was added to a given thread.
3996
 */
3997
function send_notification_mails(CForumForum $forum, CForumThread $thread, $reply_info)
3998
{
3999
    $courseEntity = api_get_course_entity($forum->getCId());
4000
    $courseId = $courseEntity->getId();
4001
4002
    $sessionId = api_get_session_id();
4003
    $sessionEntity = api_get_session_entity($sessionId);
4004
4005
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4006
4007
    // First we need to check if
4008
    // 1. the forum category is visible
4009
    // 2. the forum is visible
4010
    // 3. the thread is visible
4011
    // 4. the reply is visible (=when there is)
4012
4013
    $current_forum_category = null;
4014
    if ($forum->getForumCategory()) {
4015
        $current_forum_category = $forum->getForumCategory();
4016
    }
4017
4018
    $send_mails = false;
4019
    if ($thread->isVisible($courseEntity, $sessionEntity) &&
4020
        $forum->isVisible($courseEntity, $sessionEntity) &&
4021
        ($current_forum_category && $forum->getForumCategory()->isVisible($courseEntity, $sessionEntity)) &&
4022
        '1' != $forum->getApprovalDirectPost()
4023
    ) {
4024
        $send_mails = true;
4025
    }
4026
4027
    // The forum category, the forum, the thread and the reply are visible to the user
4028
    if ($send_mails && !empty($forum)) {
4029
        $postId = isset($reply_info['new_post_id']) ? $reply_info['new_post_id'] : 0;
4030
        send_notifications($forum, $thread, $postId);
4031
    } else {
4032
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
4033
        if ($forum) {
4034
            $sql = "SELECT * FROM $table_notification
4035
                    WHERE
4036
                        c_id = ".$courseId." AND
4037
                        (
4038
                            forum_id = '".$forum->getIid()."' OR
4039
                            thread_id = '".$thread->getIid()."'
4040
                        ) ";
4041
            $result = Database::query($sql);
4042
            $user_id = api_get_user_id();
4043
            while ($row = Database::fetch_array($result)) {
4044
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
4045
                        VALUES (".$courseId.", '".$thread->getIid()."', '".(int) ($reply_info['new_post_id'])."', '$user_id' )";
4046
                Database::query($sql);
4047
            }
4048
        }
4049
    }
4050
}
4051
4052
/**
4053
 * This function is called whenever something is made visible because there might
4054
 * be new posts and the user might have indicated that (s)he wanted to be
4055
 * informed about the new posts by mail.
4056
 *
4057
 * @param string $content Content type (post, thread, forum, forum_category)
4058
 * @param int    $id      Item DB ID of the corresponding content type
4059
 *
4060
 * @return string language variable
4061
 *
4062
 * @author Patrick Cool <[email protected]>, Ghent University
4063
 *
4064
 * @version february 2006, dokeos 1.8
4065
 */
4066
function handle_mail_cue($content, $id)
4067
{
4068
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4069
    $table_forums = Database::get_course_table(TABLE_FORUM);
4070
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4071
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4072
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4073
4074
    $course_id = api_get_course_int_id();
4075
    $id = (int) $id;
4076
4077
    /* If the post is made visible we only have to send mails to the people
4078
     who indicated that they wanted to be informed for that thread.*/
4079
    if ('post' === $content) {
4080
        // Getting the information about the post (need the thread_id).
4081
        /** @var CForumPost $post */
4082
        $post = Container::getForumPostRepository()->find($id);
4083
        $thread_id = $post->getThread()->getIid();
4084
4085
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4086
        $sql = "SELECT users.firstname, users.lastname, users.id as user_id, users.email
4087
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4088
                WHERE
4089
                    posts.c_id = $course_id AND
4090
                    mailcue.c_id = $course_id AND
4091
                    posts.thread_id = $thread_id AND
4092
                    posts.post_notification = '1' AND
4093
                    mailcue.thread_id = $thread_id AND
4094
                    users.id = posts.poster_id AND
4095
                    users.active = 1
4096
                GROUP BY users.email";
4097
4098
        $result = Database::query($sql);
4099
        $forum = Container::getForumRepository()->find($post->getForum()->getIid());
4100
4101
        while ($row = Database::fetch_array($result)) {
4102
            send_mail($row, $forum, $post->getThread(), $post);
4103
        }
4104
    } elseif ('thread' === $content) {
4105
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4106
        $sql = "SELECT users.firstname, users.lastname, users.id as user_id, users.email, posts.forum_id
4107
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4108
                WHERE
4109
                    posts.c_id = $course_id AND
4110
                    mailcue.c_id = $course_id AND
4111
                    posts.thread_id = $id AND
4112
                    posts.post_notification = '1' AND
4113
                    mailcue.thread_id = $id AND
4114
                    users.id = posts.poster_id AND
4115
                    users.active = 1
4116
                GROUP BY users.email";
4117
        $result = Database::query($sql);
4118
        while ($row = Database::fetch_array($result)) {
4119
            $forum = Container::getForumRepository()->find($row['forum_id']);
4120
            $thread = Container::getForumThreadRepository()->find($id);
4121
            send_mail($row, $forum, $thread);
4122
        }
4123
4124
        // Deleting the relevant entries from the mailcue.
4125
        $sql = "DELETE FROM $table_mailcue
4126
                WHERE c_id = $course_id AND thread_id = $id";
4127
        Database::query($sql);
4128
    } elseif ('forum' === $content) {
4129
        $sql = "SELECT iid FROM $table_threads
4130
                WHERE c_id = $course_id AND forum_id = $id";
4131
        $result = Database::query($sql);
4132
        while ($row = Database::fetch_array($result)) {
4133
            handle_mail_cue('thread', $row['iid']);
4134
        }
4135
    } elseif ('forum_category' === $content) {
4136
        $sql = "SELECT iid FROM $table_forums
4137
                WHERE c_id = $course_id AND forum_category = $id";
4138
        $result = Database::query($sql);
4139
        while ($row = Database::fetch_array($result)) {
4140
            handle_mail_cue('forum', $row['iid']);
4141
        }
4142
    } else {
4143
        return get_lang('Error');
4144
    }
4145
}
4146
4147
/**
4148
 * This function sends the mails for the mail notification.
4149
 */
4150
function send_mail($userInfo, CForumForum $forum, CForumThread $thread, CForumPost $postInfo = null)
4151
{
4152
    if (empty($userInfo) || empty($forum) || empty($thread)) {
4153
        return false;
4154
    }
4155
4156
    $_course = api_get_course_info();
4157
    $user_id = api_get_user_id();
4158
    $forumId = $forum->getIid();
4159
    $threadId = $thread->getIid();
4160
4161
    $thread_link = api_get_path(WEB_CODE_PATH).
4162
        'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$threadId;
4163
4164
    $email_body = get_lang('Dear').' '.api_get_person_name($userInfo['firstname'], $userInfo['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4165
    $email_body .= get_lang('New Post in the forum').': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4166
4167
    $courseId = api_get_configuration_value('global_forums_course_id');
4168
    $subject = get_lang('New Post in the forum').' - '.$_course['official_code'].': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4169
4170
    $courseInfoTitle = get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4171
    if (!empty($courseId) && $_course['real_id'] == $courseId) {
4172
        $subject = get_lang('New Post in the forum').': '.$forum->getForumTitle().' - '.$thread->getThreadTitle()." <br />\n";
4173
        $courseInfoTitle = " <br />\n";
4174
    }
4175
    $email_body .= $courseInfoTitle;
4176
4177
    if (!empty($postInfo)) {
4178
        $text = cut(strip_tags($postInfo->getPostText()), 100);
4179
        if (!empty($text)) {
4180
            $email_body .= get_lang('Message').": <br />\n ";
4181
            $email_body .= $text;
4182
            $email_body .= "<br /><br />\n";
4183
        }
4184
    }
4185
4186
    $email_body .= get_lang('You stated that you wanted to be informed by e-mail whenever somebody replies on the thread')."<br />\n";
4187
4188
    if (!empty($thread_link)) {
4189
        $email_body .= get_lang('The thread can be found here').' : <br /><a href="'.$thread_link.'">'.$thread_link."</a>\n";
4190
    }
4191
4192
    if ($userInfo['user_id'] != $user_id) {
4193
        MessageManager::send_message(
4194
            $userInfo['user_id'],
4195
            $subject,
4196
            $email_body,
4197
            [],
4198
            [],
4199
            null,
4200
            null,
4201
            null,
4202
            null,
4203
            $user_id
4204
        );
4205
    }
4206
}
4207
4208
/**
4209
 * This function displays the form for moving a thread to a different (already existing) forum.
4210
 *
4211
 * @author Patrick Cool <[email protected]>, Ghent University
4212
 *
4213
 * @version february 2006, dokeos 1.8
4214
 */
4215
function move_thread_form()
4216
{
4217
    $form = new FormValidator(
4218
        'movepost',
4219
        'post',
4220
        api_get_self().'?forum='.(int) ($_GET['forum']).'&thread='.(int) ($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4221
    );
4222
    $form->addHeader(get_lang('Move Thread'));
4223
    // Invisible form: the thread_id
4224
    $form->addHidden('thread_id', (int) ($_GET['thread']));
4225
    $forum_categories = get_forum_categories();
4226
4227
    $htmlcontent = '<div class="row">
4228
        <div class="label">
4229
            <span class="form_required">*</span>'.get_lang('Move to').'
4230
        </div>
4231
        <div class="formw">';
4232
    $htmlcontent .= '<select name="forum">';
4233
    foreach ($forum_categories as $category) {
4234
        $htmlcontent .= '<optgroup label="'.$category->getCatTitle().'">';
4235
        $forums = $category->getForums();
4236
        foreach ($forums as $forum) {
4237
            $htmlcontent .= '<option value="'.$forum->getIid().'">'.$forum->getForumTitle().'</option>';
4238
        }
4239
        $htmlcontent .= '</optgroup>';
4240
    }
4241
    $htmlcontent .= '</select>';
4242
    $htmlcontent .= '   </div>
4243
                    </div>';
4244
4245
    $form->addElement('html', $htmlcontent);
4246
4247
    // The OK button
4248
    $form->addButtonSave(get_lang('Move Thread'), 'SubmitForum');
4249
4250
    // Validation or display
4251
    if ($form->validate()) {
4252
        $values = $form->exportValues();
4253
        if (isset($_POST['forum'])) {
4254
            store_move_thread($values);
4255
            Display::addFlash(Display::return_message(get_lang('Moved')));
4256
        }
4257
    } else {
4258
        return $form->returnForm();
4259
    }
4260
}
4261
4262
/**
4263
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4264
 *
4265
 * @author Patrick Cool <[email protected]>, Ghent University
4266
 *
4267
 * @version february 2006, dokeos 1.8
4268
 */
4269
function move_post_form()
4270
{
4271
    $form = new FormValidator(
4272
        'movepost',
4273
        'post',
4274
        api_get_self().'?'.api_get_cidreq().'&forum='.(int) ($_GET['forum']).'&thread='.(int) ($_GET['thread']).'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post'])
4275
    );
4276
    // The header for the form
4277
    $form->addElement('header', '', get_lang('Move post'));
4278
4279
    // Invisible form: the post_id
4280
    $form->addElement('hidden', 'post_id', (int) ($_GET['post']));
4281
4282
    // Dropdown list: Threads of this forum
4283
    $threads = get_threads($_GET['forum']);
4284
    $threads_list[0] = get_lang('A new thread');
4285
    foreach ($threads as $thread) {
4286
        $threads_list[$thread->getIid()] = $thread->getThreadTitle();
4287
    }
4288
    $form->addElement('select', 'thread', get_lang('Move toThread'), $threads_list);
4289
    $form->applyFilter('thread', 'html_filter');
4290
4291
    // The OK button
4292
    $form->addButtonSave(get_lang('Move post'), 'submit');
4293
4294
    // Setting the rules
4295
    $form->addRule('thread', get_lang('Required field'), 'required');
4296
4297
    return $form;
4298
}
4299
4300
/**
4301
 * @param array $values
4302
 *
4303
 * @return string HTML language variable
4304
 *
4305
 * @author Patrick Cool <[email protected]>, Ghent University
4306
 *
4307
 * @version february 2006, dokeos 1.8
4308
 */
4309
function store_move_post($values)
4310
{
4311
    $_course = api_get_course_info();
4312
    $course_id = api_get_course_int_id();
4313
4314
    $table_forums = Database::get_course_table(TABLE_FORUM);
4315
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4316
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4317
4318
    $user = api_get_user_entity(api_get_user_id());
4319
    $course = api_get_course_entity($course_id);
4320
    $session = api_get_session_entity();
4321
4322
    if ('0' == $values['thread']) {
4323
        $repoPost = Container::getForumPostRepository();
4324
4325
        /** @var CForumPost $post */
4326
        $post = $repoPost->find($values['post_id']);
4327
        $forumId = $post->getForum()->getIid();
4328
        $threadId = $post->getThread()->getIid();
4329
4330
        $thread = new CForumThread();
4331
        $thread
4332
            ->setCId($course_id)
4333
            ->setThreadTitle($post->getPostTitle())
4334
            ->setForum($post->getForum())
4335
            ->setUser($post->getUser())
4336
            ->setThreadLastPost($post)
4337
            ->setThreadDate($post->getPostDate())
4338
            ->setParent($post->getForum())
4339
            ->addCourseLink(
4340
                $user,
4341
                $course,
4342
                $session
4343
            );
4344
4345
        $repo = Container::getForumThreadRepository();
4346
        $repo->create($thread);
4347
        $new_thread_id = $thread->getIid();
4348
4349
        // Storing a new thread.
4350
        /*$params = [
4351
            'c_id' => $course_id,
4352
            'thread_title' => $current_post['post_title'],
4353
            'forum_id' => $current_post['forum_id'],
4354
            'thread_poster_id' => $current_post['poster_id'],
4355
            'thread_poster_name' => $current_post['poster_name'],
4356
            'thread_last_post' => $values['post_id'],
4357
            'thread_date' => $current_post['post_date'],
4358
        ];
4359
4360
        $new_thread_id = Database::insert($table_threads, $params);
4361
4362
        api_item_property_update(
4363
            $_course,
4364
            TOOL_FORUM_THREAD,
4365
            $new_thread_id,
4366
            'visible',
4367
            $current_post['poster_id']
4368
        );*/
4369
4370
        // Moving the post to the newly created thread.
4371
        $sql = "UPDATE $table_posts SET thread_id='".$new_thread_id."', post_parent_id = NULL
4372
                WHERE c_id = $course_id AND iid ='".(int) ($values['post_id'])."'";
4373
        Database::query($sql);
4374
4375
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
4376
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4377
                WHERE c_id = $course_id AND post_parent_id='".(int) ($values['post_id'])."'";
4378
        Database::query($sql);
4379
4380
        // Updating updating the number of threads in the forum.
4381
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
4382
                WHERE c_id = $course_id AND iid ='".$forumId."'";
4383
        Database::query($sql);
4384
4385
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
4386
        $sql = "SELECT * FROM $table_posts
4387
                WHERE c_id = $course_id AND thread_id='".$threadId."'
4388
                ORDER BY iid DESC";
4389
        $result = Database::query($sql);
4390
        $row = Database::fetch_array($result);
4391
        $sql = "UPDATE $table_threads SET
4392
                    thread_last_post='".$row['iid']."',
4393
                    thread_replies=thread_replies-1
4394
                WHERE
4395
                    c_id = $course_id AND
4396
                    iid ='".$threadId."'";
4397
        Database::query($sql);
4398
    } else {
4399
        // Moving to the chosen thread.
4400
        $sql = 'SELECT thread_id FROM '.$table_posts."
4401
                WHERE c_id = $course_id AND iid = '".$values['post_id']."' ";
4402
        $result = Database::query($sql);
4403
        $row = Database::fetch_array($result);
4404
4405
        $original_thread_id = $row['thread_id'];
4406
        $sql = 'SELECT thread_last_post FROM '.$table_threads."
4407
                WHERE c_id = $course_id AND iid = '".$original_thread_id."' ";
4408
4409
        $result = Database::query($sql);
4410
        $row = Database::fetch_array($result);
4411
        $thread_is_last_post = $row['thread_last_post'];
4412
        // If is this thread, update the thread_last_post with the last one.
4413
4414
        if ($thread_is_last_post == $values['post_id']) {
4415
            $sql = 'SELECT iid as post_id FROM '.$table_posts."
4416
                    WHERE
4417
                        c_id = $course_id AND
4418
                        thread_id = '".$original_thread_id."' AND
4419
                        iid <> '".$values['post_id']."'
4420
                    ORDER BY post_date DESC LIMIT 1";
4421
            $result = Database::query($sql);
4422
4423
            $row = Database::fetch_array($result);
4424
            $thread_new_last_post = $row['post_id'];
4425
4426
            $sql = 'UPDATE '.$table_threads."
4427
                    SET thread_last_post = '".$thread_new_last_post."'
4428
                    WHERE c_id = $course_id AND iid = '".$original_thread_id."' ";
4429
            Database::query($sql);
4430
        }
4431
4432
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
4433
                WHERE c_id = $course_id AND iid ='".$original_thread_id."'";
4434
        Database::query($sql);
4435
4436
        // moving to the chosen thread
4437
        $sql = "UPDATE $table_posts SET thread_id='".(int) ($_POST['thread'])."', post_parent_id = NULL
4438
                WHERE c_id = $course_id AND iid ='".(int) ($values['post_id'])."'";
4439
        Database::query($sql);
4440
4441
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
4442
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4443
                WHERE c_id = $course_id AND post_parent_id='".(int) ($values['post_id'])."'";
4444
        Database::query($sql);
4445
4446
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
4447
                WHERE c_id = $course_id AND iid ='".(int) ($_POST['thread'])."'";
4448
        Database::query($sql);
4449
    }
4450
4451
    return get_lang('Thread moved');
4452
}
4453
4454
/**
4455
 * @param array $values
4456
 *
4457
 * @return string HTML language variable
4458
 *
4459
 * @author Patrick Cool <[email protected]>, Ghent University
4460
 *
4461
 * @version february 2006, dokeos 1.8
4462
 */
4463
function store_move_thread($values)
4464
{
4465
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4466
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4467
4468
    $courseId = api_get_course_int_id();
4469
    $sessionId = api_get_session_id();
4470
4471
    $forumId = (int) ($_POST['forum']);
4472
    $threadId = (int) ($_POST['thread_id']);
4473
    //$forumInfo = get_forums($forumId);
4474
4475
    // Change the thread table: Setting the forum_id to the new forum.
4476
    $sql = "UPDATE $table_threads SET forum_id = $forumId
4477
            WHERE c_id = $courseId AND iid = $threadId";
4478
    Database::query($sql);
4479
4480
    // Changing all the posts of the thread: setting the forum_id to the new forum.
4481
    $sql = "UPDATE $table_posts SET forum_id = $forumId
4482
            WHERE c_id = $courseId AND thread_id= $threadId";
4483
    Database::query($sql);
4484
4485
    // Fix group id, if forum is moved to a different group
4486
    /*if (!empty($forumInfo['to_group_id'])) {
4487
        $groupId = $forumInfo['to_group_id'];
4488
        $item = api_get_item_property_info(
4489
            $courseId,
4490
            TABLE_FORUM_THREAD,
4491
            $threadId,
4492
            $sessionId,
4493
            $groupId
4494
        );
4495
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4496
        $sessionCondition = api_get_session_condition($sessionId);
4497
4498
        if (!empty($item)) {
4499
            if ($item['to_group_id'] != $groupId) {
4500
                $sql = "UPDATE $table
4501
                    SET to_group_id = $groupId
4502
                    WHERE
4503
                      tool = '".TABLE_FORUM_THREAD."' AND
4504
                      c_id = $courseId AND
4505
                      ref = ".$item['ref']."
4506
                      $sessionCondition
4507
                ";
4508
                Database::query($sql);
4509
            }
4510
        } else {
4511
            $sql = "UPDATE $table
4512
                    SET to_group_id = $groupId
4513
                    WHERE
4514
                      tool = '".TABLE_FORUM_THREAD."' AND
4515
                      c_id = $courseId AND
4516
                      ref = ".$threadId."
4517
                      $sessionCondition
4518
            ";
4519
            Database::query($sql);
4520
        }
4521
    }*/
4522
4523
    return get_lang('Thread moved');
4524
}
4525
4526
/**
4527
 * Prepares a string for displaying by highlighting the search results inside, if any.
4528
 *
4529
 * @param string $input the input string
4530
 *
4531
 * @return string the same string with highlighted hits inside
4532
 *
4533
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
4534
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
4535
 */
4536
function prepare4display($input)
4537
{
4538
    static $highlightcolors = ['yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33'];
4539
    static $search;
4540
4541
    if (!isset($search)) {
4542
        if (isset($_POST['search_term'])) {
4543
            $search = $_POST['search_term']; // No html at all.
4544
        } elseif (isset($_GET['search'])) {
4545
            $search = $_GET['search'];
4546
        } else {
4547
            $search = '';
4548
        }
4549
    }
4550
4551
    if (!empty($search)) {
4552
        if (strstr($search, '+')) {
4553
            $search_terms = explode('+', $search);
4554
        } else {
4555
            $search_terms[] = trim($search);
4556
        }
4557
        $counter = 0;
4558
        foreach ($search_terms as $key => $search_term) {
4559
            $input = api_preg_replace(
4560
                '/'.preg_quote(trim($search_term), '/').'/i',
4561
                '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
4562
                $input
4563
            );
4564
            $counter++;
4565
        }
4566
    }
4567
4568
    // TODO: Security should be implemented outside this function.
4569
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles
4570
    // (see comments of Security::remove_XSS() method to learn about other levels).
4571
4572
    return Security::remove_XSS($input, STUDENT, true);
4573
}
4574
4575
/**
4576
 * Display the search form for the forum and display the search results.
4577
 *
4578
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4579
 *
4580
 * @version march 2008, dokeos 1.8.5
4581
 */
4582
function forum_search()
4583
{
4584
    $form = new FormValidator(
4585
        'forumsearch',
4586
        'post',
4587
        'forumsearch.php?'.api_get_cidreq()
4588
    );
4589
4590
    // Setting the form elements.
4591
    $form->addElement('header', '', get_lang('Search in the Forum'));
4592
    $form->addElement('text', 'search_term', get_lang('Search term'), ['autofocus']);
4593
    $form->applyFilter('search_term', 'html_filter');
4594
    $form->addElement('static', 'search_information', '', get_lang('Search in the ForumInformation'));
4595
    $form->addButtonSearch(get_lang('Search'));
4596
4597
    // Setting the rules.
4598
    $form->addRule('search_term', get_lang('Required field'), 'required');
4599
    $form->addRule('search_term', get_lang('Too short'), 'minlength', 3);
4600
4601
    // Validation or display.
4602
    if ($form->validate()) {
4603
        $values = $form->exportValues();
4604
        $form->setDefaults($values);
4605
        $form->display();
4606
        // Display the search results.
4607
        display_forum_search_results($values['search_term']);
4608
    } else {
4609
        $form->display();
4610
    }
4611
}
4612
4613
/**
4614
 * Display the search results.
4615
 *
4616
 * @param string $search_term
4617
 *
4618
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4619
 *
4620
 * @version march 2008, dokeos 1.8.5
4621
 */
4622
function display_forum_search_results($search_term)
4623
{
4624
    /*$table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4625
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4626
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
4627
    $session_id = api_get_session_id();
4628
    $course_id = api_get_course_int_id();
4629
4630
    // Defining the search strings as an array.
4631
    if (strstr($search_term, '+')) {
4632
        $search_terms = explode('+', $search_term);
4633
    } else {
4634
        $search_terms[] = $search_term;
4635
    }
4636
4637
    // Search restriction.
4638
    foreach ($search_terms as $value) {
4639
        $search_restriction[] = "
4640
        (
4641
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR
4642
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%'
4643
        )";
4644
    }
4645
4646
    $sessionCondition = api_get_session_condition(
4647
        $session_id,
4648
        true,
4649
        false,
4650
        'item_property.session_id'
4651
    );
4652
4653
    $sql = "SELECT posts.*
4654
            FROM $table_posts posts
4655
            INNER JOIN $table_threads threads
4656
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
4657
            INNER JOIN $table_item_property item_property
4658
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
4659
            WHERE
4660
                posts.c_id = $course_id AND
4661
                item_property.c_id = $course_id AND
4662
                item_property.visibility = 1
4663
                $sessionCondition AND
4664
                posts.visible = 1 AND
4665
                item_property.tool = '".TOOL_FORUM_THREAD."' AND
4666
                ".implode(' AND ', $search_restriction).'
4667
            GROUP BY posts.post_id';
4668
4669
    // Getting all the information of the forum categories.
4670
    $forum_categories_list = get_forum_categories();
4671
4672
    // Getting all the information of the forums.
4673
    $forum_list = get_forums();
4674
4675
    $result = Database::query($sql);
4676
    $search_results = [];
4677
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4678
        $forumId = $row['forum_id'];
4679
        $forumData = get_forums($forumId);
4680
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
4681
        $display_result = false;
4682
4683
//          We only show it when
4684
//          1. forum category is visible
4685
//          2. forum is visible
4686
//          3. thread is visible (to do)
4687
//          4. post is visible
4688
4689
        if (!api_is_allowed_to_edit(null, true)) {
4690
            if (!empty($category)) {
4691
                if ('1' == $category['visibility'] && '1' == $forumData['visibility']) {
4692
                    $display_result = true;
4693
                }
4694
            } else {
4695
                if ('1' == $forumData['visible']) {
4696
                    $display_result = true;
4697
                }
4698
            }
4699
        } else {
4700
            $display_result = true;
4701
        }
4702
4703
        if ($display_result) {
4704
            $categoryName = !empty($category) ? $category['cat_title'] : '';
4705
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
4706
                prepare4display($categoryName).'</a> &gt; ';
4707
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
4708
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
4709
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
4710
                prepare4display($row['post_title']).'</a>';
4711
            $search_results_item .= '<br />';
4712
            if (api_strlen($row['post_title']) > 200) {
4713
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
4714
            } else {
4715
                $search_results_item .= prepare4display($row['post_title']);
4716
            }
4717
            $search_results_item .= '</li>';
4718
            $search_results[] = $search_results_item;
4719
        }
4720
    }
4721
    echo '<legend>'.count($search_results).' '.get_lang('Search in the ForumResults').'</legend>';
4722
    echo '<ol>';
4723
    if ($search_results) {
4724
        echo implode($search_results);
4725
    }
4726
    echo '</ol>';*/
4727
}
4728
4729
/**
4730
 * Return the link to the forum search page.
4731
 *
4732
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4733
 *
4734
 * @version April 2008, dokeos 1.8.5
4735
 */
4736
function search_link()
4737
{
4738
    // @todo implement search
4739
4740
    return '';
4741
4742
    $return = '';
0 ignored issues
show
Unused Code introduced by
$return = '' 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...
4743
    $origin = api_get_origin();
4744
    if ('learnpath' != $origin) {
4745
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
4746
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
4747
4748
        if (!empty($_GET['search'])) {
4749
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
4750
            $url = api_get_self().'?';
4751
            $url_parameter = [];
4752
            foreach ($_GET as $key => $value) {
4753
                if ('search' != $key) {
4754
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
4755
                }
4756
            }
4757
            $url .= implode('&', $url_parameter);
4758
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('Clean search results')).'</a>';
4759
        }
4760
    }
4761
4762
    return $return;
4763
}
4764
4765
/**
4766
 * This function adds an attachment file into a forum.
4767
 *
4768
 * @param string     $file_comment a comment about file
4769
 * @param CForumPost $post         from forum_post table
4770
 *
4771
 * @return false|null
4772
 */
4773
function add_forum_attachment_file($file_comment, CForumPost $post)
4774
{
4775
    $request = Container::getRequest();
4776
    if (false === $request->files->has('user_upload')) {
4777
        return false;
4778
    }
4779
4780
    $file = $request->files->get('user_upload');
4781
    if (empty($file)) {
4782
        return false;
4783
    }
4784
4785
    $files = [];
4786
    if ($file instanceof UploadedFile) {
4787
        $files[] = $file;
4788
    } else {
4789
        $files = $file;
4790
    }
4791
4792
    /** @var UploadedFile $attachment */
4793
    foreach ($files as $file) {
4794
        $valid = process_uploaded_file($file);
4795
4796
        if (!$valid) {
4797
            continue;
4798
        }
4799
4800
        // Try to add an extension to the file if it hasn't one.
4801
        $new_file_name = add_ext_on_mime(
4802
            stripslashes($file->getPathname()),
4803
            $file->getType()
4804
        );
4805
4806
        // User's file name
4807
        $file_name = $file->getClientOriginalName();
4808
4809
        if (!filter_extension($new_file_name)) {
4810
            Display::addFlash(
4811
                Display::return_message(
4812
                    get_lang('File upload failed: this file extension or file type is prohibited'),
4813
                    'error'
4814
                )
4815
            );
4816
4817
            return;
4818
        }
4819
4820
        $safe_file_comment = Database::escape_string($file_comment);
4821
4822
        $user = api_get_user_entity(api_get_user_id());
4823
        $course = api_get_course_entity(api_get_course_int_id());
4824
        $session = api_get_session_entity(api_get_session_id());
4825
4826
        $attachment = new CForumAttachment();
4827
        $attachment
4828
            ->setCId(api_get_course_int_id())
4829
            ->setComment($safe_file_comment)
4830
            ->setFilename($file_name)
4831
            ->setPath($file_name)
4832
            ->setPost($post)
4833
            ->setSize($file->getSize())
4834
            ->setParent($post)
4835
            ->addCourseLink(
4836
                $course,
4837
                $session
4838
            );
4839
4840
        $repo = Container::getForumAttachmentRepository();
4841
        $repo->create($attachment);
4842
        $repo->addFile($attachment, $file);
4843
        $repo->update($attachment);
4844
4845
        /*$last_id_file = Database::insert(
4846
            $agenda_forum_attachment,
4847
            [
4848
                'path' => $safe_new_file_name,
4849
            ]
4850
        );*/
4851
4852
        /*api_item_property_update(
4853
            $_course,
4854
            TOOL_FORUM_ATTACH,
4855
            $last_id_file,
4856
            'ForumAttachmentAdded',
4857
            api_get_user_id()
4858
        );*/
4859
    }
4860
}
4861
4862
/**
4863
 * This function edits an attachment file into a forum.
4864
 *
4865
 * @param string $file_comment a comment about file
4866
 * @param int    $post_id
4867
 * @param int    $id_attach    attachment file Id
4868
 */
4869
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
4870
{
4871
    throw new Exception('edit_forum_attachment_file');
4872
    /*
4873
    $_course = api_get_course_info();
4874
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4875
    $course_id = api_get_course_int_id();
4876
4877
    $filesData = [];
4878
4879
    if (!is_array($_FILES['user_upload']['name'])) {
4880
        $filesData[] = $_FILES['user_upload'];
4881
    } else {
4882
        $fileCount = count($_FILES['user_upload']['name']);
4883
        $fileKeys = array_keys($_FILES['user_upload']);
4884
4885
        for ($i = 0; $i < $fileCount; $i++) {
4886
            foreach ($fileKeys as $key) {
4887
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
4888
            }
4889
        }
4890
    }
4891
4892
    foreach ($filesData as $attachment) {
4893
        if (empty($attachment['name'])) {
4894
            continue;
4895
        }
4896
4897
        $upload_ok = process_uploaded_file($attachment);
4898
4899
        if (!$upload_ok) {
4900
            continue;
4901
        }
4902
4903
        $course_dir = $_course['path'].'/upload/forum';
4904
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
4905
        $updir = $sys_course_path.$course_dir;
4906
4907
        // Try to add an extension to the file if it hasn't one.
4908
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
4909
        // User's file name
4910
        $file_name = $attachment['name'];
4911
4912
        if (!filter_extension($new_file_name)) {
4913
            Display::addFlash(
4914
                Display::return_message(
4915
                    get_lang('File upload failed: this file extension or file type is prohibited'),
4916
                    'error'
4917
                )
4918
            );
4919
        } else {
4920
            $new_file_name = uniqid('');
4921
            $new_path = $updir.'/'.$new_file_name;
4922
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
4923
            $safe_file_comment = Database::escape_string($file_comment);
4924
            $safe_file_name = Database::escape_string($file_name);
4925
            $safe_new_file_name = Database::escape_string($new_file_name);
4926
            $safe_post_id = (int) $post_id;
4927
            $safe_id_attach = (int) $id_attach;
4928
            // Storing the attachments if any.
4929
            if ($result) {
4930
                $sql = "UPDATE $table_forum_attachment
4931
                        SET
4932
                            filename = '$safe_file_name',
4933
                            comment = '$safe_file_comment',
4934
                            path = '$safe_new_file_name',
4935
                            post_id = '$safe_post_id',
4936
                            size ='".$attachment['size']."'
4937
                        WHERE c_id = $course_id AND id = '$safe_id_attach'";
4938
                Database::query($sql);
4939
                api_item_property_update(
4940
                    $_course,
4941
                    TOOL_FORUM_ATTACH,
4942
                    $safe_id_attach,
4943
                    'ForumAttachmentUpdated',
4944
                    api_get_user_id()
4945
                );
4946
            }
4947
        }
4948
    }*/
4949
}
4950
4951
/**
4952
 * Show a list with all the attachments according to the post's id.
4953
 *
4954
 * @param int $postId
4955
 *
4956
 * @return array with the post info
4957
 *
4958
 * @author Julio Montoya
4959
 *
4960
 * @version avril 2008, dokeos 1.8.5
4961
 */
4962
function get_attachment($postId)
4963
{
4964
    $table = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4965
    $course_id = api_get_course_int_id();
4966
    $row = [];
4967
    $postId = (int) $postId;
4968
4969
    if (empty($postId)) {
4970
        return [];
4971
    }
4972
4973
    $sql = "SELECT iid, path, filename, comment
4974
            FROM $table
4975
            WHERE c_id = $course_id AND post_id = $postId";
4976
    $result = Database::query($sql);
4977
    if (0 != Database::num_rows($result)) {
4978
        $row = Database::fetch_array($result);
4979
    }
4980
4981
    return $row;
4982
}
4983
4984
/**
4985
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional).
4986
 *
4987
 * @param int $postId
4988
 * @param int $attachmentId
4989
 *
4990
 * @return bool
4991
 */
4992
function delete_attachment($postId, $attachmentId)
4993
{
4994
    $repo = Container::getForumPostRepository();
4995
    $em = Database::getManager();
4996
    /** @var CForumPost $post */
4997
    $post = $repo->find($postId);
4998
    if ($post) {
4999
        $repoAttachment = Container::getForumAttachmentRepository();
5000
        $attachment = $repoAttachment->find($attachmentId);
5001
        if ($attachment) {
5002
            $post->removeAttachment($attachment);
5003
            $em->remove($attachment);
5004
        }
5005
        $repo->update($post);
5006
5007
        Display::addFlash(Display::return_message(get_lang('The attached file has been deleted'), 'confirmation'));
5008
    }
5009
5010
    return true;
5011
5012
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
0 ignored issues
show
Unused Code introduced by
$forum_table_attachment ...TABLE_FORUM_ATTACHMENT) is not reachable.

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

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

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

    return false;
}

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

Loading history...
5013
    $course_id = api_get_course_int_id();
5014
5015
    $cond = !empty($id_attach) ? ' iid = '.(int) $id_attach.'' : ' post_id = '.(int) $post_id.'';
5016
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
5017
    $res = Database::query($sql);
5018
    $row = Database::fetch_array($res);
5019
5020
    $course_dir = $_course['path'].'/upload/forum';
5021
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
5022
    $updir = $sys_course_path.$course_dir;
5023
    $my_path = isset($row['path']) ? $row['path'] : null;
5024
    $file = $updir.'/'.$my_path;
5025
    if (Security::check_abs_path($file, $updir)) {
5026
        @unlink($file);
5027
    }
5028
5029
    // Delete from forum_attachment table.
5030
    $sql = "DELETE FROM $forum_table_attachment
5031
            WHERE c_id = $course_id AND $cond ";
5032
    $result = Database::query($sql);
5033
    if (false !== $result) {
5034
        $affectedRows = Database::affected_rows($result);
5035
    } else {
5036
        $affectedRows = 0;
5037
    }
5038
5039
    // Update item_property.
5040
    api_item_property_update(
5041
        $_course,
5042
        TOOL_FORUM_ATTACH,
5043
        $id_attach,
5044
        'ForumAttachmentDelete',
5045
        api_get_user_id()
5046
    );
5047
5048
    if (!empty($result) && !empty($id_attach)) {
5049
        Display::addFlash(Display::return_message(get_lang('The attached file has been deleted'), 'confirmation'));
5050
    }
5051
5052
    return $affectedRows;
5053
}
5054
5055
/**
5056
 * This function gets all the forum information of the all the forum of the group.
5057
 *
5058
 * @param array $groupInfo the id of the group we need the fora of (see forum.forum_of_group)
5059
 *
5060
 * @return CForumForum[]
5061
 *
5062
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
5063
 */
5064
function get_forums_of_group(CGroup $group)
5065
{
5066
    $course = api_get_course_entity();
5067
    $session = api_get_session_entity();
5068
    $repo = Container::getForumRepository();
5069
    $qb = $repo->getResourcesByCourse($course, $session, $group);
5070
5071
    return $qb->getQuery()->getResult();
5072
5073
    $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...
5074
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5075
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5076
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5077
    $course_id = api_get_course_int_id();
5078
    $groupId = (int) $groupInfo['id'];
5079
5080
    // Student
5081
    // Select all the forum information of all forums (that are visible to students).
5082
    $sql = "SELECT * FROM $table_forums forum
5083
            INNER JOIN $table_item_property item_properties
5084
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5085
            WHERE
5086
                forum.forum_of_group = $groupId AND
5087
                forum.c_id = $course_id AND
5088
                item_properties.c_id = $course_id AND
5089
                item_properties.visibility = 1 AND
5090
                item_properties.tool = '".TOOL_FORUM."'
5091
            ORDER BY forum.forum_order ASC";
5092
5093
    // Select the number of threads of the forums (only the threads that are visible).
5094
    $sql2 = "SELECT
5095
                count(thread_id) AS number_of_threads,
5096
                threads.forum_id
5097
            FROM $table_threads threads
5098
            INNER JOIN $table_item_property item_properties
5099
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5100
            WHERE
5101
                threads.c_id = $course_id AND
5102
                item_properties.c_id = $course_id AND
5103
                item_properties.visibility = 1 AND
5104
                item_properties.tool='".TOOL_FORUM_THREAD."'
5105
            GROUP BY threads.forum_id";
5106
5107
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
5108
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
5109
            FROM $table_posts posts
5110
            INNER JOIN $table_threads threads
5111
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5112
            INNER JOIN $table_item_property item_properties
5113
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5114
            WHERE
5115
                posts.visible=1 AND
5116
                posts.c_id = $course_id AND
5117
                item_properties.c_id = $course_id AND
5118
                threads.c_id = $course_id AND
5119
                item_properties.visibility = 1 AND
5120
                item_properties.tool='".TOOL_FORUM_THREAD."'
5121
            GROUP BY threads.forum_id";
5122
5123
    // Course Admin
5124
    if (api_is_allowed_to_edit()) {
5125
        // Select all the forum information of all forums (that are not deleted).
5126
        $sql = "SELECT *
5127
                FROM $table_forums forum
5128
                INNER JOIN $table_item_property item_properties
5129
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5130
                WHERE
5131
                    forum.forum_of_group = $groupId AND
5132
                    forum.c_id = $course_id AND
5133
                    item_properties.c_id = $course_id AND
5134
                    item_properties.visibility <> 2 AND
5135
                    item_properties.tool = '".TOOL_FORUM."'
5136
                ORDER BY forum_order ASC";
5137
5138
        // Select the number of threads of the forums (only the threads that are not deleted).
5139
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
5140
                 FROM $table_threads threads
5141
                 INNER JOIN $table_item_property item_properties
5142
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
5143
                 WHERE
5144
                    threads.c_id = $course_id AND
5145
                    item_properties.c_id = $course_id AND
5146
                    item_properties.visibility <> 2 AND
5147
                    item_properties.tool='".TOOL_FORUM_THREAD."'
5148
                GROUP BY threads.forum_id";
5149
        // Select the number of posts of the forum.
5150
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
5151
                FROM $table_posts
5152
                WHERE c_id = $course_id
5153
                GROUP BY forum_id";
5154
    }
5155
5156
    // Handling all the forum information.
5157
    $result = Database::query($sql);
5158
    $forum_list = [];
5159
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5160
        $forum_list[$row['forum_id']] = $row;
5161
    }
5162
5163
    // Handling the thread count information.
5164
    $result2 = Database::query($sql2);
5165
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5166
        if (is_array($forum_list)) {
5167
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5168
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5169
            }
5170
        }
5171
    }
5172
5173
    // Handling the post count information.
5174
    $result3 = Database::query($sql3);
5175
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5176
        if (is_array($forum_list)) {
5177
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5178
                // This is needed because sql3 takes also the deleted forums into account.
5179
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5180
            }
5181
        }
5182
    }
5183
5184
    // Finding the last post information
5185
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5186
    if (!empty($forum_list)) {
5187
        foreach ($forum_list as $key => $value) {
5188
            $lastPost = get_last_post_information($key, api_is_allowed_to_edit());
5189
            if ($lastPost) {
5190
                $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
5191
                $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
5192
                $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
5193
                $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
5194
                $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
5195
                $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
5196
            }
5197
        }
5198
    }
5199
5200
    return $forum_list;
5201
}
5202
5203
/**
5204
 * This function stores which users have to be notified of which forums or threads.
5205
 *
5206
 * @param string $content    does the user want to be notified about a forum or about a thread
5207
 * @param int    $id         the id of the forum or thread
5208
 * @param bool   $addOnly
5209
 * @param array  $userInfo
5210
 * @param array  $courseInfo
5211
 *
5212
 * @return string language variable
5213
 *
5214
 * @author  Patrick Cool <[email protected]>, Ghent University, Belgium
5215
 * @author  Julio Montoya
5216
 *
5217
 * @since   May 2008 v1.8.5
5218
 */
5219
function set_notification($content, $id, $addOnly = false, $userInfo = [], $courseInfo = [])
5220
{
5221
    $userInfo = empty($userInfo) ? api_get_user_info() : $userInfo;
5222
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
5223
    $id = (int) $id;
5224
5225
    if (empty($userInfo) || empty($courseInfo) || empty($id) || empty($content)) {
5226
        return false;
5227
    }
5228
5229
    // Database table definition
5230
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5231
    $course_id = $courseInfo['real_id'];
5232
5233
    // Which database field do we have to store the id in?
5234
    $field = 'thread_id';
5235
    if ('forum' === $content) {
5236
        $field = 'forum_id';
5237
    }
5238
5239
    $userId = $userInfo['user_id'];
5240
5241
    // First we check if the notification is already set for this.
5242
    $sql = "SELECT * FROM $table_notification
5243
            WHERE
5244
                c_id = $course_id AND
5245
                $field = $id AND
5246
                user_id = $userId ";
5247
    $result = Database::query($sql);
5248
    $total = Database::num_rows($result);
5249
5250
    // If the user did not indicate that (s)he wanted to be notified already
5251
    // then we store the notification request (to prevent double notification requests).
5252
    if ($total <= 0) {
5253
        $notification = new CForumNotification();
5254
        $notification
5255
            ->setCId($course_id)
5256
            ->setUserId($userId)
5257
        ;
5258
5259
        if ('forum' === $content) {
5260
            $notification->setForumId($id);
5261
        } else {
5262
            $notification->setThreadId($id);
5263
        }
5264
5265
        $em = Database::getManager();
5266
        $em->persist($notification);
5267
        $em->flush();
5268
5269
        Session::erase('forum_notification');
5270
        getNotificationsPerUser(0, true);
5271
5272
        return get_lang('You will be notified of new posts by e-mail.');
5273
    } else {
5274
        if (!$addOnly) {
5275
            $sql = "DELETE FROM $table_notification
5276
                    WHERE
5277
                        c_id = $course_id AND
5278
                        $field = $id AND
5279
                        user_id = $userId ";
5280
            Database::query($sql);
5281
            Session::erase('forum_notification');
5282
            getNotificationsPerUser(0, true);
5283
5284
            return get_lang('You will no longer be notified of new posts by email');
5285
        }
5286
    }
5287
}
5288
5289
/**
5290
 * This function retrieves all the email adresses of the users who wanted to be notified
5291
 * about a new post in a certain forum or thread.
5292
 *
5293
 * @param string $content does the user want to be notified about a forum or about a thread
5294
 * @param int    $id      the id of the forum or thread
5295
 *
5296
 * @return array returns
5297
 *
5298
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5299
 * @author Julio Montoya
5300
 *
5301
 * @version May 2008, dokeos 1.8.5
5302
 *
5303
 * @since May 2008, dokeos 1.8.5
5304
 */
5305
function get_notifications($content, $id)
5306
{
5307
    // Database table definition
5308
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5309
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5310
    $course_id = api_get_course_int_id();
5311
5312
    // Which database field contains the notification?
5313
    $field = 'thread_id';
5314
    if ('forum' === $content) {
5315
        $field = 'forum_id';
5316
    }
5317
5318
    $id = (int) $id;
5319
5320
    $sql = "SELECT user.id as user_id, user.firstname, user.lastname, user.email, user.id user
5321
            FROM $table_users user, $table_notification notification
5322
            WHERE
5323
                notification.c_id = $course_id AND user.active = 1 AND
5324
                user.id = notification.user_id AND
5325
                notification.$field = $id ";
5326
5327
    $result = Database::query($sql);
5328
    $return = [];
5329
5330
    while ($row = Database::fetch_array($result)) {
5331
        $return['user'.$row['user_id']] = ['email' => $row['email'], 'user_id' => $row['user_id']];
5332
    }
5333
5334
    return $return;
5335
}
5336
5337
/**
5338
 * Get all the users who need to receive a notification of a new post (those subscribed to
5339
 * the forum or the thread).
5340
 *
5341
 * @param int $post_id the id of the post
5342
 *
5343
 * @return false|null
5344
 *
5345
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5346
 *
5347
 * @version May 2008, dokeos 1.8.5
5348
 *
5349
 * @since May 2008, dokeos 1.8.5
5350
 */
5351
function send_notifications(CForumForum $forum, CForumThread $thread, $post_id = 0)
5352
{
5353
    if (!$forum) {
5354
        return false;
5355
    }
5356
5357
    // Users who subscribed to the forum
5358
    $users_to_be_notified_by_forum = get_notifications('forum', $forum->getIid());
5359
5360
    // User who subscribed to the thread
5361
    $users_to_be_notified_by_thread = [];
5362
    if (!$thread) {
5363
        $users_to_be_notified_by_thread = get_notifications('thread', $thread->getIid());
5364
    }
5365
5366
    $postInfo = null;
5367
    if (!empty($post_id)) {
5368
        $postInfo = Container::getForumPostRepository()->find($post_id);
5369
    }
5370
5371
    // Merging the two
5372
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
5373
5374
    if (is_array($users_to_be_notified)) {
5375
        foreach ($users_to_be_notified as $value) {
5376
            $userInfo = api_get_user_info($value['user_id']);
5377
            send_mail($userInfo, $forum, $thread, $postInfo);
5378
        }
5379
    }
5380
}
5381
5382
/**
5383
 * Get all the notification subscriptions of the user
5384
 * = which forums and which threads does the user wants to be informed of when a new
5385
 * post is added to this thread.
5386
 *
5387
 * @param int  $user_id the user_id of a user (default = 0 => the current user)
5388
 * @param bool $force   force get the notification subscriptions (even if the information is already in the session
5389
 *
5390
 * @return array
5391
 *
5392
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5393
 *
5394
 * @version May 2008, dokeos 1.8.5
5395
 *
5396
 * @since May 2008, dokeos 1.8.5
5397
 */
5398
function getNotificationsPerUser($user_id = 0, $force = false, $course_id = 0)
5399
{
5400
    // Database table definition
5401
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5402
    $course_id = empty($course_id) ? api_get_course_int_id() : (int) $course_id;
5403
    if (empty($course_id) || -1 == $course_id) {
5404
        return null;
5405
    }
5406
5407
    $user_id = empty($user_id) ? api_get_user_id() : (int) $user_id;
5408
5409
    if (!isset($_SESSION['forum_notification']) ||
5410
        $_SESSION['forum_notification']['course'] != $course_id ||
5411
        true == $force
5412
    ) {
5413
        $_SESSION['forum_notification']['course'] = $course_id;
5414
        $sql = "SELECT * FROM $table_notification
5415
                WHERE c_id = $course_id AND user_id='".$user_id."'";
5416
5417
        $result = Database::query($sql);
5418
        while ($row = Database::fetch_array($result)) {
5419
            if (null !== $row['forum_id']) {
5420
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
5421
            }
5422
            if (null !== $row['thread_id']) {
5423
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
5424
            }
5425
        }
5426
    }
5427
}
5428
5429
/**
5430
 * This function counts the number of post inside a thread.
5431
 *
5432
 * @param int $thread_id
5433
 *
5434
 * @return int the number of post inside a thread
5435
 *
5436
 * @author Jhon Hinojosa <[email protected]>,
5437
 *
5438
 * @version octubre 2008, dokeos 1.8
5439
 */
5440
function count_number_of_post_in_thread($thread_id)
5441
{
5442
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5443
    $course_id = api_get_course_int_id();
5444
    if (empty($course_id)) {
5445
        return 0;
5446
    }
5447
    $sql = "SELECT count(*) count FROM $table_posts
5448
            WHERE
5449
                c_id = $course_id AND
5450
                thread_id='".(int) $thread_id."' ";
5451
    $result = Database::query($sql);
5452
5453
    $count = 0;
5454
    if (Database::num_rows($result) > 0) {
5455
        $row = Database::fetch_array($result);
5456
        $count = $row['count'];
5457
    }
5458
5459
    return $count;
5460
}
5461
5462
/**
5463
 * This function counts the number of post inside a thread user.
5464
 *
5465
 * @param int $thread_id
5466
 * @param int $user_id
5467
 *
5468
 * @return int the number of post inside a thread user
5469
 */
5470
function count_number_of_post_for_user_thread($thread_id, $user_id)
5471
{
5472
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5473
    $course_id = api_get_course_int_id();
5474
    $sql = "SELECT count(iid) as count
5475
            FROM $table_posts
5476
            WHERE c_id = $course_id AND
5477
                  thread_id=".(int) $thread_id.' AND
5478
                  poster_id = '.(int) $user_id.' AND visible = 1 ';
5479
    $result = Database::query($sql);
5480
    $count = 0;
5481
    if (Database::num_rows($result) > 0) {
5482
        $count = Database::fetch_array($result);
5483
        $count = $count['count'];
5484
    }
5485
5486
    return $count;
5487
}
5488
5489
/**
5490
 * This function retrieves information of statistical.
5491
 *
5492
 * @param int $thread_id
5493
 * @param int $user_id
5494
 * @param int $course_id
5495
 *
5496
 * @return array the information of statistical
5497
 *
5498
 * @author Jhon Hinojosa <[email protected]>,
5499
 *
5500
 * @version oct 2008, dokeos 1.8
5501
 */
5502
function get_statistical_information($thread_id, $user_id, $course_id)
5503
{
5504
    $result = [];
5505
    $courseInfo = api_get_course_info_by_id($course_id);
5506
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
5507
    $result['post'] = count_number_of_post_in_thread($thread_id);
5508
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
5509
5510
    return $result;
5511
}
5512
5513
/**
5514
 * This function return the posts inside a thread from a given user.
5515
 *
5516
 * @param \Chamilo\CoreBundle\Entity\Course $course
5517
 * @param int                               $thread_id
5518
 * @param int                               $user_id
5519
 *
5520
 * @return array posts inside a thread
5521
 *
5522
 * @author  Jhon Hinojosa <[email protected]>,
5523
 *
5524
 * @version oct 2008, dokeos 1.8
5525
 */
5526
function get_thread_user_post(Course $course, $thread_id, $user_id)
5527
{
5528
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5529
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5530
    $thread_id = (int) $thread_id;
5531
    $user_id = (int) $user_id;
5532
    $course_id = $course->getId();
5533
5534
    if (empty($course_id)) {
5535
        $course_id = api_get_course_int_id();
5536
    }
5537
    $sql = "SELECT *, user.id as user_id FROM $table_posts posts
5538
            LEFT JOIN $table_users user
5539
            ON posts.poster_id = user.id
5540
            WHERE
5541
                posts.c_id = $course_id AND
5542
                posts.thread_id='$thread_id' AND
5543
                posts.poster_id='$user_id'
5544
            ORDER BY posts.iid ASC";
5545
5546
    $result = Database::query($sql);
5547
    $post_list = [];
5548
    while ($row = Database::fetch_array($result)) {
5549
        $row['status'] = '1';
5550
        $post_list[] = $row;
5551
        $sql = "SELECT * FROM $table_posts posts
5552
                LEFT JOIN $table_users users
5553
                ON (posts.poster_id=users.id)
5554
                WHERE
5555
                    posts.c_id = $course_id AND
5556
                    posts.thread_id='$thread_id'
5557
                    AND posts.post_parent_id='".$row['iid']."'
5558
                ORDER BY posts.iid ASC";
5559
        $result2 = Database::query($sql);
5560
        while ($row2 = Database::fetch_array($result2)) {
5561
            $row2['status'] = '0';
5562
            $post_list[] = $row2;
5563
        }
5564
    }
5565
5566
    return $post_list;
5567
}
5568
5569
/**
5570
 * This function get the name of an thread by id.
5571
 *
5572
 * @param int $thread_id
5573
 *
5574
 * @return string
5575
 *
5576
 * @author Christian Fasanando
5577
 * @author Julio Montoya <[email protected]> Adding security
5578
 */
5579
function get_name_thread_by_id($thread_id)
5580
{
5581
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
5582
    $course_id = api_get_course_int_id();
5583
    $sql = "SELECT thread_title
5584
            FROM $t_forum_thread
5585
            WHERE c_id = $course_id AND iid = '".(int) $thread_id."' ";
5586
    $result = Database::query($sql);
5587
    $row = Database::fetch_array($result);
5588
5589
    return $row[0];
5590
}
5591
5592
/**
5593
 * This function gets all the post written by an user.
5594
 *
5595
 * @param int $user_id
5596
 *
5597
 * @return string
5598
 */
5599
function get_all_post_from_user($user_id, $courseId)
5600
{
5601
    $j = 0;
5602
    $forums = get_forums($courseId);
5603
    krsort($forums);
5604
    $forum_results = '';
5605
5606
    foreach ($forums as $forum) {
5607
        $forumId = $forum->getIid();
5608
5609
        /*if (0 == $forum['visibility']) {
5610
            continue;
5611
        }*/
5612
        if ($j <= 4) {
5613
            $threads = get_threads($forumId);
5614
5615
            if ($threads) {
5616
                $i = 0;
5617
                $hand_forums = '';
5618
                $post_counter = 0;
5619
                foreach ($threads as $thread) {
5620
                    /*if (0 == $thread['visibility']) {
5621
                        continue;
5622
                    }*/
5623
                    if ($i <= 4) {
5624
                        $post_list = get_thread_user_post_limit(
5625
                            $courseId,
5626
                            $thread->getIid(),
5627
                            $user_id,
5628
                            1
5629
                        );
5630
                        $post_counter = count($post_list);
5631
                        if (is_array($post_list) && count($post_list) > 0) {
5632
                            $hand_forums .= '<div id="social-thread">';
5633
                            $hand_forums .= Display::return_icon(
5634
                                'thread.png',
5635
                                get_lang('Thread'),
5636
                                '',
5637
                                ICON_SIZE_MEDIUM
5638
                            );
5639
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread->getThreadTitle(), STUDENT);
5640
                            $hand_forums .= '</div>';
5641
5642
                            foreach ($post_list as $posts) {
5643
                                $hand_forums .= '<div id="social-post">';
5644
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
5645
                                $hand_forums .= '<br / >';
5646
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
5647
                                $hand_forums .= '</div>';
5648
                                $hand_forums .= '<br / >';
5649
                            }
5650
                        }
5651
                    }
5652
                    $i++;
5653
                }
5654
                $forum_results .= '<div id="social-forum">';
5655
                $forum_results .= '<div class="clear"></div><br />';
5656
                $forum_results .= '<div id="social-forum-title">'.
5657
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum->getForumTitle(), STUDENT).
5658
                    '<div style="float:right;margin-top:-35px">
5659
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($courseId).'&forum='.$forum->getIid().' " >'.
5660
                    get_lang('See forum').'
5661
                        </a>
5662
                     </div></div>';
5663
                $forum_results .= '<br / >';
5664
                if ($post_counter > 0) {
5665
                    $forum_results .= $hand_forums;
5666
                }
5667
                $forum_results .= '</div>';
5668
            }
5669
            $j++;
5670
        }
5671
    }
5672
5673
    return $forum_results;
5674
}
5675
5676
/**
5677
 * @param int $thread_id
5678
 * @param int $user_id
5679
 * @param int $limit
5680
 *
5681
 * @return array
5682
 */
5683
function get_thread_user_post_limit($courseId, $thread_id, $user_id, $limit = 10)
5684
{
5685
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5686
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5687
5688
    $courseId = (int) $courseId;
5689
5690
    $sql = "SELECT * FROM $table_posts posts
5691
            LEFT JOIN $table_users users
5692
                ON posts.poster_id=users.id
5693
            WHERE
5694
                posts.c_id = $courseId AND
5695
                posts.thread_id='".Database::escape_string($thread_id)."' AND
5696
                posts.poster_id='".Database::escape_string($user_id)."'
5697
            ORDER BY posts.post_id DESC LIMIT $limit ";
5698
    $result = Database::query($sql);
5699
    $post_list = [];
5700
    while ($row = Database::fetch_array($result)) {
5701
        $row['status'] = '1';
5702
        $post_list[] = $row;
5703
    }
5704
5705
    return $post_list;
5706
}
5707
5708
/**
5709
 * @param string $userId
5710
 * @param array  $courseInfo
5711
 * @param int    $sessionId
5712
 *
5713
 * @return array
5714
 */
5715
function getForumCreatedByUser($userId, $courseInfo, $sessionId)
5716
{
5717
    if (empty($userId) || empty($courseInfo)) {
5718
        return [];
5719
    }
5720
5721
    $courseId = $courseInfo['real_id'];
5722
5723
    $repo = Container::getForumRepository();
5724
5725
    $courseEntity = api_get_course_entity($courseId);
5726
    $sessionEntity = api_get_session_entity($sessionId);
5727
5728
    $qb = $repo->getResourcesByCourse($courseEntity, $sessionEntity);
5729
5730
    $qb->andWhere('node.creator = :creator');
5731
    $qb->setParameter('creator', $userId);
5732
    $items = $qb->getQuery()->getResult();
5733
5734
    $forumList = [];
5735
    if (!empty($items)) {
5736
        /** @var CForumForum $forum */
5737
        foreach ($items as $forum) {
5738
            $forumList[] = [
5739
                $forum->getForumTitle(),
5740
                api_get_local_time($forum->getResourceNode()->getCreatedAt()),
5741
                api_get_local_time($forum->getResourceNode()->getUpdatedAt()),
5742
            ];
5743
        }
5744
    }
5745
5746
    return $forumList;
5747
}
5748
5749
/**
5750
 * This function builds an array of all the posts in a given thread
5751
 * where the key of the array is the post_id
5752
 * It also adds an element children to the array which itself is an array
5753
 * that contains all the id's of the first-level children.
5754
 *
5755
 * @return array containing all the information on the posts of a thread
5756
 *
5757
 * @author Patrick Cool <[email protected]>, Ghent University
5758
 */
5759
function calculate_children($rows)
5760
{
5761
    $sorted_rows = [0 => []];
5762
    if (!empty($rows)) {
5763
        foreach ($rows as $row) {
5764
            $rows_with_children[$row['post_id']] = $row;
5765
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
5766
        }
5767
5768
        $rows = $rows_with_children;
5769
        forumRecursiveSort($rows, $sorted_rows);
5770
        unset($sorted_rows[0]);
5771
    }
5772
5773
    return $sorted_rows;
5774
}
5775
5776
/**
5777
 * @param $rows
5778
 * @param $threads
5779
 * @param int $seed
5780
 * @param int $indent
5781
 */
5782
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
5783
{
5784
    if ($seed > 0) {
5785
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
5786
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
5787
        $indent++;
5788
    }
5789
5790
    if (isset($rows[$seed]['children'])) {
5791
        foreach ($rows[$seed]['children'] as $child) {
5792
            forumRecursiveSort($rows, $threads, $child, $indent);
5793
        }
5794
    }
5795
}
5796
5797
/**
5798
 * Update forum attachment data, used to update comment and post ID.
5799
 *
5800
 * @param array $array    (field => value) to update forum attachment row
5801
 * @param int   $id       ID to find row to update
5802
 * @param int   $courseId course ID to find row to update
5803
 *
5804
 * @return int number of affected rows
5805
 */
5806
function editAttachedFile($array, $id, $courseId = null)
5807
{
5808
    // Init variables
5809
    $setString = '';
5810
    $id = (int) $id;
5811
    $courseId = (int) $courseId;
5812
    if (empty($courseId)) {
5813
        // $courseId can be null, use api method
5814
        $courseId = api_get_course_int_id();
5815
    }
5816
    /*
5817
     * Check if Attachment ID and Course ID are greater than zero
5818
     * and array of field values is not empty
5819
     */
5820
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
5821
        foreach ($array as $key => &$item) {
5822
            $item = Database::escape_string($item);
5823
            $setString .= $key.' = "'.$item.'", ';
5824
        }
5825
        // Delete last comma
5826
        $setString = substr($setString, 0, strlen($setString) - 2);
5827
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5828
        $sql = "UPDATE $forumAttachmentTable
5829
                SET $setString WHERE c_id = $courseId AND id = $id";
5830
        $result = Database::query($sql);
5831
        if (false !== $result) {
5832
            $affectedRows = Database::affected_rows($result);
5833
            if ($affectedRows > 0) {
5834
                /*
5835
                 * If exist in $_SESSION variable, then delete them from it
5836
                 * because they would be deprecated
5837
                 */
5838
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
5839
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
5840
                }
5841
            }
5842
5843
            return $affectedRows;
5844
        }
5845
    }
5846
5847
    return 0;
5848
}
5849
5850
/**
5851
 * Return a table where the attachments will be set.
5852
 *
5853
 * @param int $postId Forum Post ID
5854
 *
5855
 * @return string The Forum Attachments Ajax Table
5856
 */
5857
function getAttachmentsAjaxTable($postId = 0)
5858
{
5859
    $postId = (int) $postId;
5860
    $courseId = api_get_course_int_id();
5861
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
5862
    $fileDataContent = '';
5863
    // Update comment to show if form did not pass validation
5864
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
5865
        // 'file_ids is the name from forum attachment ajax form
5866
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
5867
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
5868
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
5869
            ) {
5870
                // If exist forum attachment then update into $_SESSION data
5871
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
5872
            }
5873
        }
5874
    }
5875
5876
    // Get data to fill into attachment files table
5877
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
5878
        is_array($_SESSION['forum']['upload_file'][$courseId])
5879
    ) {
5880
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
5881
        foreach ($uploadedFiles as $k => $uploadedFile) {
5882
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
5883
                // Buil html table including an input with attachmentID
5884
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
5885
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
5886
                    $uploadedFile['delete'].'</td>'.
5887
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
5888
            } else {
5889
                /*
5890
                 * If attachment data is empty, then delete it from $_SESSION
5891
                 * because could generate and empty row into html table
5892
                 */
5893
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
5894
            }
5895
        }
5896
    }
5897
    $style = empty($fileDataContent) ? 'display: none;' : '';
5898
    // Forum attachment Ajax table
5899
    return '
5900
    <div class="control-group " style="'.$style.'">
5901
        <label class="control-label">'.get_lang('Attachments list').'</label>
5902
        <div class="controls">
5903
            <table id="attachmentFileList" class="files data_table span10">
5904
                <tr>
5905
                    <th>'.get_lang('Filename').'</th>
5906
                    <th>'.get_lang('Size').'</th>
5907
                    <th>'.get_lang('Status').'</th>
5908
                    <th>'.get_lang('Comment').'</th>
5909
                    <th>'.get_lang('Delete').'</th>
5910
                </tr>
5911
                '.$fileDataContent.'
5912
            </table>
5913
        </div>
5914
    </div>';
5915
}
5916
5917
/**
5918
 * Return an array of prepared attachment data to build forum attachment table
5919
 * Also, save this array into $_SESSION to do available the attachment data.
5920
 *
5921
 * @param int $forumId
5922
 * @param int $threadId
5923
 * @param int $postId
5924
 * @param int $attachId
5925
 * @param int $courseId
5926
 *
5927
 * @return array
5928
 */
5929
function getAttachedFiles(
5930
    $forumId,
5931
    $threadId,
5932
    $postId = 0,
5933
    $attachId = 0,
5934
    $courseId = 0
5935
) {
5936
    $forumId = (int) $forumId;
5937
    $courseId = (int) $courseId;
5938
    $attachId = (int) $attachId;
5939
    $postId = (int) $postId;
5940
    $threadId = (int) $threadId;
5941
5942
    if (empty($courseId)) {
5943
        // $courseId can be null, use api method
5944
        $courseId = api_get_course_int_id();
5945
    }
5946
    if (empty($forumId)) {
5947
        if (!empty($_REQUEST['forum'])) {
5948
            $forumId = (int) $_REQUEST['forum'];
5949
        } else {
5950
            // if forum ID is empty, cannot generate delete url
5951
5952
            return [];
5953
        }
5954
    }
5955
    // Check if exist at least one of them to filter forum attachment select query
5956
    if (empty($postId) && empty($attachId)) {
5957
        return [];
5958
    }
5959
5960
    if (empty($postId)) {
5961
        $filter = "AND iid = $attachId";
5962
    } elseif (empty($attachId)) {
5963
        $filter = "AND post_id = $postId";
5964
    } else {
5965
        $filter = "AND post_id = $postId AND iid = $attachId";
5966
    }
5967
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5968
    $sql = "SELECT iid
5969
            FROM $forumAttachmentTable
5970
            WHERE c_id = $courseId $filter";
5971
    $result = Database::query($sql);
5972
    $json = [];
5973
    if (Database::num_rows($result) > 0) {
5974
        $repo = Container::getForumAttachmentRepository();
5975
        while ($row = Database::fetch_array($result, 'ASSOC')) {
5976
            /** @var CForumAttachment $attachment */
5977
            $attachment = $repo->find($row['iid']);
5978
            $downloadUrl = $repo->getResourceFileDownloadUrl($attachment);
5979
5980
            // name contains an URL to download attachment file and its filename
5981
            $json['name'] = Display::url(
5982
                api_htmlentities($attachment->getFilename()),
5983
                $downloadUrl,
5984
                ['target' => '_blank', 'class' => 'attachFilename']
5985
            );
5986
            $json['id'] = $row['iid'];
5987
            $json['comment'] = $attachment->getComment();
5988
            // Format file size
5989
            $json['size'] = format_file_size($attachment->getSize());
5990
            // Check if $row is consistent
5991
            if ($attachment) {
5992
                // Set result as success and bring delete URL
5993
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded.'));
5994
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
5995
                $json['delete'] = Display::url(
5996
                    Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL),
5997
                    $url,
5998
                    ['class' => 'deleteLink']
5999
                );
6000
            } else {
6001
                // If not, set an exclamation result
6002
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
6003
            }
6004
            // Store array data into $_SESSION
6005
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
6006
        }
6007
    }
6008
6009
    return $json;
6010
}
6011
6012
/**
6013
 * Clear forum attachment data stored in $_SESSION,
6014
 * If is not defined post, it will clear all forum attachment data from course.
6015
 *
6016
 * @param int $postId   -1 : Clear all attachments from course stored in $_SESSION
6017
 *                      0 : Clear attachments from course, except from temporal post "0"
6018
 *                      but without delete them from file system and database
6019
 *                      Other values : Clear attachments from course except specified post
6020
 *                      and delete them from file system and database
6021
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
6022
 *
6023
 * @return array
6024
 */
6025
function clearAttachedFiles($postId = 0, $courseId = 0)
6026
{
6027
    // Init variables
6028
    $courseId = (int) $courseId;
6029
    $postId = (int) $postId;
6030
    $array = [];
6031
    if (empty($courseId)) {
6032
        // $courseId can be null, use api method
6033
        $courseId = api_get_course_int_id();
6034
    }
6035
    if (-1 === $postId) {
6036
        // If post ID is -1 then delete course's attachment data from $_SESSION
6037
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
6038
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
6039
            unset($_SESSION['forum']['upload_file'][$courseId]);
6040
        }
6041
    } else {
6042
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
6043
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
6044
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
6045
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
6046
                if (!in_array($attachId, $attachIds)) {
6047
                    // If attach ID is not into specified post, delete attachment
6048
                    // Save deleted attachment ID
6049
                    $array[] = $attachId;
6050
                    if (0 !== $postId) {
6051
                        // Post 0 is temporal, delete them from file system and DB
6052
                        delete_attachment(0, $attachId);
6053
                    }
6054
                    // Delete attachment data from $_SESSION
6055
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
6056
                }
6057
            }
6058
        }
6059
    }
6060
6061
    return $array;
6062
}
6063
6064
/**
6065
 * Returns an array of forum attachment ids into a course and forum post.
6066
 *
6067
 * @param int $postId
6068
 * @param int $courseId
6069
 *
6070
 * @return array
6071
 */
6072
function getAttachmentIdsByPostId($postId, $courseId = 0)
6073
{
6074
    $array = [];
6075
    $courseId = (int) $courseId;
6076
    $postId = (int) $postId;
6077
    if (empty($courseId)) {
6078
        // $courseId can be null, use api method
6079
        $courseId = api_get_course_int_id();
6080
    }
6081
    if ($courseId > 0) {
6082
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6083
        $sql = "SELECT iid FROM $forumAttachmentTable
6084
                WHERE c_id = $courseId AND post_id = $postId";
6085
        $result = Database::query($sql);
6086
        if (false !== $result && Database::num_rows($result) > 0) {
6087
            while ($row = Database::fetch_array($result, 'ASSOC')) {
6088
                $array[] = $row['iid'];
6089
            }
6090
        }
6091
    }
6092
6093
    return $array;
6094
}
6095
6096
/**
6097
 * Check if the forum category exists looking for its title.
6098
 *
6099
 * @param string $title     The forum category title
6100
 * @param int    $courseId  The course ID
6101
 * @param int    $sessionId Optional. The session ID
6102
 *
6103
 * @return bool
6104
 */
6105
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
6106
{
6107
    $repo = Container::getForumCategoryRepository();
6108
    $course = api_get_course_entity($courseId);
6109
    $session = api_get_session_entity($sessionId);
6110
6111
    return $repo->findResourceByTitle(
6112
        $title,
6113
        $course->getResourceNode(),
6114
        $course,
6115
        $session
6116
    );
6117
6118
    /*$sessionId = (int) $sessionId;
6119
    $courseId = (int) $courseId;
6120
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
6121
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
6122
6123
    $fakeFrom = "$forumCategoryTable fc
6124
        INNER JOIN $itemProperty ip ";
6125
6126
    if (0 === $sessionId) {
6127
        $fakeFrom .= '
6128
            ON (
6129
                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)
6130
            )
6131
        ';
6132
    } else {
6133
        $fakeFrom .= '
6134
            ON (
6135
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
6136
            )
6137
        ';
6138
    }
6139
6140
    $resultData = Database::select(
6141
        'fc.*',
6142
        $fakeFrom,
6143
        [
6144
            'where' => [
6145
                'ip.visibility != ? AND ' => 2,
6146
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
6147
                'fc.session_id = ? AND ' => $sessionId,
6148
                'fc.cat_title = ? AND ' => $title,
6149
                'fc.c_id = ?' => $courseId,
6150
            ],
6151
        ],
6152
        'first'
6153
    );
6154
6155
    if (empty($resultData)) {
6156
        return false;
6157
    }
6158
6159
    return $resultData;*/
6160
}
6161
6162
/**
6163
 * @param array $row
6164
 * @param bool  $addWrapper
6165
 *
6166
 * @return string
6167
 */
6168
function getPostStatus(CForumForum $forum, $row, $addWrapper = true)
6169
{
6170
    $statusIcon = '';
6171
    if ($forum->isModerated()) {
6172
        if ($addWrapper) {
6173
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
6174
        }
6175
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
6176
6177
        $addUrl = false;
6178
        $showStatus = false;
6179
        if (api_is_allowed_to_edit(false, true)) {
6180
            $addUrl = true;
6181
        } else {
6182
            if ($row['user_id'] == api_get_user_id()) {
6183
                $showStatus = true;
6184
            }
6185
        }
6186
6187
        $label = '';
6188
        $icon = '';
6189
        $buttonType = '';
6190
        switch ($row['status']) {
6191
            case CForumPost::STATUS_VALIDATED:
6192
                $label = get_lang('Validated');
6193
                $icon = 'check-circle';
6194
                $buttonType = 'success';
6195
6196
                break;
6197
            case CForumPost::STATUS_WAITING_MODERATION:
6198
                $label = get_lang('Waiting for moderation');
6199
                $icon = 'warning';
6200
                $buttonType = 'warning';
6201
6202
                break;
6203
            case CForumPost::STATUS_REJECTED:
6204
                $label = get_lang('Rejected');
6205
                $icon = 'minus-circle';
6206
                $buttonType = 'danger';
6207
6208
                break;
6209
        }
6210
6211
        if ($addUrl) {
6212
            $statusIcon .= Display::toolbarButton(
6213
                $label.'&nbsp;',
6214
                'javascript:void(0)',
6215
                $icon,
6216
                $buttonType,
6217
                ['class' => 'change_post_status']
6218
            );
6219
        } else {
6220
            if ($showStatus) {
6221
                $statusIcon .= Display::label(
6222
                    Display::returnFontAwesomeIcon($icon).$label,
6223
                    $buttonType
6224
                );
6225
            }
6226
        }
6227
6228
        if ($addWrapper) {
6229
            $statusIcon .= '</span>';
6230
        }
6231
    }
6232
6233
    return $statusIcon;
6234
}
6235
6236
/**
6237
 * @param CForumForum $forum
6238
 * @param int         $threadId
6239
 * @param int         $status
6240
 */
6241
function getCountPostsWithStatus($status, $forum, $threadId = null)
6242
{
6243
    $em = Database::getManager();
6244
    $criteria = Criteria::create();
6245
    $criteria
6246
        ->where(Criteria::expr()->eq('status', $status))
6247
        ->andWhere(Criteria::expr()->eq('cId', $forum->getCId()))
6248
        ->andWhere(Criteria::expr()->eq('visible', 1))
6249
    ;
6250
6251
    if (!empty($threadId)) {
6252
        $criteria->andWhere(Criteria::expr()->eq('thread', $threadId));
6253
    }
6254
6255
    $qb = $em->getRepository(CForumPost::class)->createQueryBuilder('p');
6256
    $qb->select('count(p.iid)')
6257
        ->addCriteria($criteria);
6258
6259
    return $qb->getQuery()->getSingleScalarResult();
6260
}
6261
6262
/**
6263
 * @param CForumForum $forum
6264
 * @param CForumPost  $post
6265
 *
6266
 * @return bool
6267
 */
6268
function postIsEditableByStudent($forum, $post)
6269
{
6270
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6271
        return true;
6272
    }
6273
6274
    if (1 == $forum->isModerated()) {
6275
        if (null === $post->getStatus()) {
6276
            return true;
6277
        } else {
6278
            return in_array(
6279
                $post->getStatus(),
6280
                [
6281
                    CForumPost::STATUS_WAITING_MODERATION,
6282
                    CForumPost::STATUS_REJECTED,
6283
                ]
6284
            );
6285
        }
6286
    }
6287
6288
    return true;
6289
}
6290
6291
/**
6292
 * @return bool
6293
 */
6294
function savePostRevision(CForumPost $post)
6295
{
6296
    $userId = api_get_user_id();
6297
6298
    if ($post->getUser()->getId() != $userId) {
6299
        return false;
6300
    }
6301
6302
    $status = (int) !postNeedsRevision($post);
6303
    $extraFieldValue = new ExtraFieldValue('forum_post');
6304
    $params = [
6305
        'item_id' => $post->getIid(),
6306
        'extra_ask_for_revision' => ['extra_ask_for_revision' => $status],
6307
    ];
6308
    if (empty($status)) {
6309
        unset($params['extra_ask_for_revision']);
6310
    }
6311
    $extraFieldValue->saveFieldValues(
6312
        $params,
6313
        true,
6314
        false,
6315
        ['ask_for_revision']
6316
    );
6317
}
6318
6319
/**
6320
 * @param int $postId
6321
 *
6322
 * @return string
6323
 */
6324
function getPostRevision($postId)
6325
{
6326
    $extraFieldValue = new ExtraFieldValue('forum_post');
6327
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6328
        $postId,
6329
        'revision_language'
6330
    );
6331
    $revision = '';
6332
    if ($value && isset($value['value'])) {
6333
        $revision = $value['value'];
6334
    }
6335
6336
    return $revision;
6337
}
6338
6339
function postNeedsRevision(CForumPost $post): bool
6340
{
6341
    $postId = $post->getIid();
6342
    $extraFieldValue = new ExtraFieldValue('forum_post');
6343
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6344
        $postId,
6345
        'ask_for_revision'
6346
    );
6347
    $hasRevision = false;
6348
    if ($value && isset($value['value'])) {
6349
        return 1 == $value['value'];
6350
    }
6351
6352
    return $hasRevision;
6353
}
6354
6355
/**
6356
 * @param array $threadInfo
6357
 *
6358
 * @return string
6359
 */
6360
function getAskRevisionButton(CForumPost $post, $threadInfo)
6361
{
6362
    if (false === api_get_configuration_value('allow_forum_post_revisions')) {
6363
        return '';
6364
    }
6365
6366
    $postId = $post->getIid();
6367
6368
    $status = 'btn-default';
6369
    if (postNeedsRevision($post)) {
6370
        $status = 'btn-success';
6371
    }
6372
6373
    return Display::url(
6374
        get_lang('Ask for a revision'),
6375
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6376
        api_get_cidreq().'&action=ask_revision&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6377
        ['class' => "btn $status", 'title' => get_lang('Ask for a revision')]
6378
    );
6379
}
6380
6381
/**
6382
 * @param int   $postId
6383
 * @param array $threadInfo
6384
 *
6385
 * @return string
6386
 */
6387
function giveRevisionButton($postId, $threadInfo)
6388
{
6389
    $postId = (int) $postId;
6390
6391
    return Display::toolbarButton(
6392
        get_lang('Give revision'),
6393
        api_get_path(WEB_CODE_PATH).'forum/reply.php?'.api_get_cidreq().'&'.http_build_query(
6394
            [
6395
                'forum' => $threadInfo['forum_id'],
6396
                'thread' => $threadInfo['thread_id'],
6397
                'post' => $postId = (int) $postId,
6398
                'action' => 'replymessage',
6399
                'give_revision' => 1,
6400
            ]
6401
        ),
6402
        'reply',
6403
        'primary',
6404
        ['id' => "reply-to-post-{$postId}"]
6405
    );
6406
}
6407
6408
/**
6409
 * @param int   $postId
6410
 * @param array $threadInfo
6411
 *
6412
 * @return string
6413
 */
6414
function getReportButton($postId, $threadInfo)
6415
{
6416
    $postId = (int) $postId;
6417
6418
    return Display::url(
6419
        Display::returnFontAwesomeIcon('flag'),
6420
        api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.
6421
        api_get_cidreq().'&action=report&post_id='.$postId.'&forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'],
6422
        ['class' => 'btn btn-danger', 'title' => get_lang('Report')]
6423
    );
6424
}
6425
6426
/**
6427
 * @return bool
6428
 */
6429
function reportAvailable()
6430
{
6431
    $extraFieldValue = new ExtraFieldValue('course');
6432
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6433
        api_get_course_int_id(),
6434
        'allow_forum_report_button'
6435
    );
6436
    $allowReport = false;
6437
    if ($value && isset($value['value']) && 1 == $value['value']) {
6438
        $allowReport = true;
6439
    }
6440
6441
    return $allowReport;
6442
}
6443
6444
/**
6445
 * @return array
6446
 */
6447
function getReportRecipients()
6448
{
6449
    $extraFieldValue = new ExtraFieldValue('course');
6450
    $value = $extraFieldValue->get_values_by_handler_and_field_variable(
6451
        api_get_course_int_id(),
6452
        'forum_report_recipients'
6453
    );
6454
    $users = [];
6455
    if ($value && isset($value['value'])) {
6456
        $usersType = explode(';', $value['value']);
6457
6458
        foreach ($usersType as $type) {
6459
            switch ($type) {
6460
                case 'teachers':
6461
                    $teachers = CourseManager::get_teacher_list_from_course_code(api_get_course_id());
6462
                    if (!empty($teachers)) {
6463
                        $users = array_merge($users, array_column($teachers, 'user_id'));
6464
                    }
6465
6466
                break;
6467
                case 'admins':
6468
                    $admins = UserManager::get_all_administrators();
6469
                    if (!empty($admins)) {
6470
                        $users = array_merge($users, array_column($admins, 'user_id'));
6471
                    }
6472
6473
                    break;
6474
                case 'community_managers':
6475
                    $managers = api_get_configuration_value('community_managers_user_list');
6476
                    if (!empty($managers) && isset($managers['users'])) {
6477
                        $users = array_merge($users, $managers['users']);
6478
                    }
6479
6480
                    break;
6481
            }
6482
        }
6483
6484
        $users = array_unique(array_filter($users));
6485
    }
6486
6487
    return $users;
6488
}
6489
6490
/**
6491
 * @param array $forumInfo
6492
 * @param array $threadInfo
6493
 *
6494
 * @return bool
6495
 */
6496
function reportPost(CForumPost $post, $forumInfo, $threadInfo)
6497
{
6498
    if (!reportAvailable()) {
6499
        return false;
6500
    }
6501
6502
    if (empty($forumInfo) || empty($threadInfo)) {
6503
        return false;
6504
    }
6505
6506
    $postId = $post->getIid();
6507
6508
    $currentUser = api_get_user_info();
6509
    $users = getReportRecipients();
6510
    if (!empty($users)) {
6511
        $url = api_get_path(WEB_CODE_PATH).
6512
            'forum/viewthread.php?forum='.$threadInfo['forum_id'].'&thread='.$threadInfo['thread_id'].'&'.api_get_cidreq().'&post_id='.$postId.'#post_id_'.$postId;
6513
        $postLink = Display::url(
6514
            $post->getPostTitle(),
6515
            $url
6516
        );
6517
        $subject = get_lang('Post reported');
6518
        $content = sprintf(
6519
            get_lang('User %s has reported the message %s in the forum %s'),
6520
            $currentUser['complete_name'],
6521
            $postLink,
6522
            $forumInfo['forum_title']
6523
        );
6524
        foreach ($users as $userId) {
6525
            MessageManager::send_message_simple($userId, $subject, $content);
6526
        }
6527
    }
6528
}
6529