Passed
Push — master ( 3398ac...23e37a )
by Julito
10:22
created

getAllAttachment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

    return false;
}

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

Loading history...
1385
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1386
1387
    // Condition for the session
1388
    $session_id = $sessionId ?: api_get_session_id();
1389
    $course_id = $courseId ?: api_get_course_int_id();
1390
1391
    $condition_session = api_get_session_condition(
1392
        $session_id,
1393
        true,
1394
        true,
1395
        'forum_categories.session_id'
1396
    );
1397
    $condition_session .= " AND forum_categories.c_id = $course_id AND item_properties.c_id = $course_id";
1398
1399
    if (empty($id)) {
1400
        $sql = "SELECT *
1401
                FROM $table_item_property item_properties
1402
                INNER JOIN $table_categories forum_categories
1403
                ON (
1404
                    forum_categories.cat_id = item_properties.ref AND
1405
                    item_properties.c_id = forum_categories.c_id
1406
                )
1407
                WHERE
1408
                    item_properties.visibility = 1 AND
1409
                    item_properties.tool = '".TOOL_FORUM_CATEGORY."'
1410
                    $condition_session
1411
                ORDER BY forum_categories.cat_order ASC";
1412
        if (api_is_allowed_to_edit()) {
1413
            $sql = "SELECT *
1414
                    FROM $table_item_property item_properties
1415
                    INNER JOIN $table_categories forum_categories
1416
                    ON (
1417
                        forum_categories.cat_id = item_properties.ref AND
1418
                        item_properties.c_id = forum_categories.c_id
1419
                    )
1420
                    WHERE
1421
                        item_properties.visibility<>2 AND
1422
                        item_properties.tool='".TOOL_FORUM_CATEGORY."'
1423
                        $condition_session
1424
                    ORDER BY forum_categories.cat_order ASC";
1425
        }
1426
    } else {
1427
        $sql = "SELECT *
1428
                FROM $table_item_property item_properties
1429
                INNER JOIN $table_categories forum_categories
1430
                ON (
1431
                    forum_categories.cat_id = item_properties.ref AND
1432
                    item_properties.c_id = forum_categories.c_id
1433
                )
1434
                WHERE
1435
                    item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
1436
                    forum_categories.cat_id = ".(int) $id."
1437
                    $condition_session
1438
                ORDER BY forum_categories.cat_order ASC";
1439
    }
1440
1441
    $result = Database::query($sql);
1442
    $forum_categories_list = [];
1443
    $extraFieldValue = new ExtraFieldValue('forum_category');
1444
    while ($row = Database::fetch_assoc($result)) {
1445
        $row['extra_fields'] = $extraFieldValue->getAllValuesByItem($row['cat_id']);
1446
1447
        if (empty($id)) {
1448
            $forum_categories_list[$row['cat_id']] = $row;
1449
        } else {
1450
            $forum_categories_list = $row;
1451
        }
1452
    }
1453
1454
    return $forum_categories_list;
1455
}
1456
1457
/**
1458
 * This function retrieves all the fora in a given forum category.
1459
 *
1460
 * @param int $cat_id   the id of the forum category
1461
 * @param int $courseId Optional. The course ID
1462
 *
1463
 * @return CForumForum[] containing all the information about the forums (regardless of their category)
1464
 *
1465
 * @author Patrick Cool <[email protected]>, Ghent University
1466
 *
1467
 * @version february 2006, dokeos 1.8
1468
 */
1469
function get_forums_in_category($cat_id, $courseId = 0)
1470
{
1471
    $repo = Container::getForumRepository();
1472
    $course = api_get_course_entity($courseId);
1473
1474
    $qb = $repo->getResourcesByCourse($course, null);
1475
    $qb->andWhere('resource.forumCategory = :catId')
1476
        ->setParameter('catId', $cat_id);
1477
1478
    return $qb->getQuery()->getResult();
1479
1480
    $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...
1481
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1482
1483
    $forum_list = [];
1484
    $course_id = $courseId ?: api_get_course_int_id();
1485
    $cat_id = (int) $cat_id;
1486
1487
    $sql = "SELECT * FROM $table_forums forum
1488
            INNER JOIN $table_item_property item_properties
1489
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1490
            WHERE
1491
                forum.forum_category = '".$cat_id."' AND
1492
                item_properties.visibility = 1 AND
1493
                forum.c_id = $course_id AND
1494
                item_properties.c_id = $course_id AND
1495
                item_properties.tool = '".TOOL_FORUM."'
1496
            ORDER BY forum.forum_order ASC";
1497
    if (api_is_allowed_to_edit()) {
1498
        $sql = "SELECT * FROM $table_forums forum
1499
                INNER JOIN $table_item_property item_properties
1500
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1501
                WHERE
1502
                    forum.forum_category = '".$cat_id."' AND
1503
                    item_properties.visibility <> 2 AND
1504
                    item_properties.tool = '".TOOL_FORUM."' AND
1505
                    item_properties.c_id = $course_id AND
1506
                    forum.c_id = $course_id
1507
                ORDER BY forum_order ASC";
1508
    }
1509
    $result = Database::query($sql);
1510
    while ($row = Database::fetch_array($result)) {
1511
        $forum_list[$row['forum_id']] = $row;
1512
    }
1513
1514
    return $forum_list;
1515
}
1516
1517
/**
1518
 * Retrieve all the forums (regardless of their category) or of only one.
1519
 * The forums are sorted according to the forum_order.
1520
 * Since it does not take the forum category into account there probably
1521
 * will be two or more forums that have forum_order=1, ...
1522
 *
1523
 * @param int  $id                 forum id
1524
 * @param bool $includeGroupsForum
1525
 * @param int  $sessionId
1526
 *
1527
 * @return CForumForum[]
1528
 */
1529
function get_forums(
1530
    $id = 0,
1531
    $courseId = '',
1532
    $includeGroupsForum = true,
1533
    $sessionId = 0
1534
) {
1535
    $repo = Container::getForumRepository();
1536
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
1537
    $course = api_get_course_entity($courseId);
1538
    $session = api_get_session_entity($sessionId);
1539
1540
    $qb = $repo->getResourcesByCourse($course, $session);
1541
1542
    /*$qb->andWhere('resource.forumCategory = :catId')
1543
        ->setParameter('catId', $cat_id);
1544
    */
1545
    return $qb->getQuery()->getResult();
1546
1547
    $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...
1548
    $course_info = api_get_course_info($course_code);
1549
1550
    $table_forums = Database::get_course_table(TABLE_FORUM);
1551
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1552
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1553
1554
    // Condition for the session
1555
    $session_id = (int) $sessionId ?: api_get_session_id();
1556
    $sessionIdLink = 0 === $session_id ? '' : ' AND threads.session_id = item_properties.session_id';
1557
1558
    $condition_session = api_get_session_condition(
1559
        $session_id,
1560
        true,
1561
        false,
1562
        'item_properties.session_id'
1563
    );
1564
1565
    $course_id = $course_info['real_id'];
1566
1567
    $forum_list = [];
1568
    $includeGroupsForumSelect = '';
1569
    if (!$includeGroupsForum) {
1570
        $includeGroupsForumSelect = ' AND (forum_of_group = 0 OR forum_of_group IS NULL) ';
1571
    }
1572
1573
    $allowToEdit = api_is_allowed_to_edit();
1574
1575
    if (empty($id)) {
1576
        // Student
1577
        // Select all the forum information of all forums (that are visible to students).
1578
        $sql = "SELECT item_properties.*, forum.*
1579
                FROM $table_forums forum
1580
                INNER JOIN $table_item_property item_properties
1581
                ON (
1582
                    forum.forum_id = item_properties.ref AND
1583
                    forum.c_id = item_properties.c_id
1584
                )
1585
                WHERE
1586
                    item_properties.visibility = 1 AND
1587
                    item_properties.tool = '".TOOL_FORUM."'
1588
                    $condition_session AND
1589
                    forum.c_id = $course_id AND
1590
                    item_properties.c_id = $course_id
1591
                    $includeGroupsForumSelect
1592
                ORDER BY forum.forum_order ASC";
1593
1594
        // Select the number of threads of the forums (only the threads that are visible).
1595
        $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1596
                FROM $table_threads threads
1597
                INNER JOIN $table_item_property item_properties
1598
                ON (
1599
                    threads.thread_id = item_properties.ref AND
1600
                    threads.c_id = item_properties.c_id
1601
                    $sessionIdLink
1602
                )
1603
                WHERE
1604
                    item_properties.visibility=1 AND
1605
                    item_properties.tool='".TOOL_FORUM_THREAD."' AND
1606
                    threads.c_id = $course_id AND
1607
                    item_properties.c_id = $course_id
1608
                GROUP BY threads.forum_id";
1609
1610
        // Course Admin
1611
        if ($allowToEdit) {
1612
            // Select all the forum information of all forums (that are not deleted).
1613
            $sql = "SELECT item_properties.*, forum.*
1614
                    FROM $table_forums forum
1615
                    INNER JOIN $table_item_property item_properties
1616
                    ON (
1617
                        forum.forum_id = item_properties.ref AND
1618
                        forum.c_id = item_properties.c_id
1619
                    )
1620
                    WHERE
1621
                        item_properties.visibility <> 2 AND
1622
                        item_properties.tool = '".TOOL_FORUM."'
1623
                        $condition_session AND
1624
                        forum.c_id = $course_id AND
1625
                        item_properties.c_id = $course_id
1626
                        $includeGroupsForumSelect
1627
                    ORDER BY forum_order ASC";
1628
1629
            // Select the number of threads of the forums (only the threads that are not deleted).
1630
            $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1631
                    FROM $table_threads threads
1632
                    INNER JOIN $table_item_property item_properties
1633
                    ON (
1634
                        threads.thread_id = item_properties.ref AND
1635
                        threads.c_id = item_properties.c_id
1636
                        $sessionIdLink
1637
                    )
1638
                    WHERE
1639
                        item_properties.visibility<>2 AND
1640
                        item_properties.tool='".TOOL_FORUM_THREAD."' AND
1641
                        threads.c_id = $course_id AND
1642
                        item_properties.c_id = $course_id
1643
                    GROUP BY threads.forum_id";
1644
        }
1645
    } else {
1646
        // GETTING ONE SPECIFIC FORUM
1647
        /* We could do the splitup into student and course admin also but we want
1648
        to have as much as information about a certain forum as possible
1649
        so we do not take too much information into account. This function
1650
         (or this section of the function) is namely used to fill the forms
1651
        when editing a forum (and for the moment it is the only place where
1652
        we use this part of the function) */
1653
1654
        // Select all the forum information of the given forum (that is not deleted).
1655
        $sql = "SELECT * FROM $table_item_property item_properties
1656
                INNER JOIN $table_forums forum
1657
                ON (forum.forum_id = item_properties.ref AND forum.c_id = item_properties.c_id)
1658
                WHERE
1659
                    forum.forum_id = $id AND
1660
                    forum.c_id = $course_id AND
1661
                    item_properties.visibility != 2 AND
1662
                    item_properties.tool = '".TOOL_FORUM."'
1663
                ORDER BY forum_order ASC";
1664
1665
        // Select the number of threads of the forum.
1666
        $sql2 = "SELECT count(*) AS number_of_threads, forum_id
1667
                FROM $table_threads
1668
                WHERE
1669
                    forum_id = $id
1670
                GROUP BY forum_id";
1671
    }
1672
1673
    // Handling all the forum information.
1674
    $result = Database::query($sql);
1675
    while ($row = Database::fetch_assoc($result)) {
1676
        if (empty($id)) {
1677
            $forum_list[$row['forum_id']] = $row;
1678
        } else {
1679
            $forum_list = $row;
1680
        }
1681
    }
1682
1683
    // Handling the thread count information.
1684
    $result2 = Database::query($sql2);
1685
    while ($row2 = Database::fetch_array($result2)) {
1686
        if (empty($id)) {
1687
            $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
1688
        } else {
1689
            $forum_list['number_of_threads'] = $row2['number_of_threads'];
1690
        }
1691
    }
1692
1693
    /* Finding the last post information
1694
    (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)*/
1695
    if (empty($id)) {
1696
        if (is_array($forum_list)) {
1697
            foreach ($forum_list as $key => $value) {
1698
                $lastPost = get_last_post_information(
1699
                    $key,
1700
                    $allowToEdit,
1701
                    $course_id
1702
                );
1703
1704
                if ($lastPost) {
1705
                    $forum_list[$key]['last_post_id'] = $lastPost['last_post_id'];
1706
                    $forum_list[$key]['last_poster_id'] = $lastPost['last_poster_id'];
1707
                    $forum_list[$key]['last_post_date'] = $lastPost['last_post_date'];
1708
                    $forum_list[$key]['last_poster_name'] = $lastPost['last_poster_name'];
1709
                    $forum_list[$key]['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1710
                    $forum_list[$key]['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1711
                    $forum_list[$key]['last_post_title'] = $lastPost['last_post_title'];
1712
                    $forum_list[$key]['last_post_text'] = $lastPost['last_post_text'];
1713
                }
1714
            }
1715
        } else {
1716
            $forum_list = [];
1717
        }
1718
    } else {
1719
        $lastPost = get_last_post_information(
1720
            $id,
1721
            $allowToEdit,
1722
            $course_id
1723
        );
1724
        if ($lastPost) {
1725
            $forum_list['last_post_id'] = $lastPost['last_post_id'];
1726
            $forum_list['last_poster_id'] = $lastPost['last_poster_id'];
1727
            $forum_list['last_post_date'] = $lastPost['last_post_date'];
1728
            $forum_list['last_poster_name'] = $lastPost['last_poster_name'];
1729
            $forum_list['last_poster_lastname'] = $lastPost['last_poster_lastname'];
1730
            $forum_list['last_poster_firstname'] = $lastPost['last_poster_firstname'];
1731
            $forum_list['last_post_title'] = $lastPost['last_post_title'];
1732
            $forum_list['last_post_text'] = $lastPost['last_post_text'];
1733
        }
1734
    }
1735
1736
    return $forum_list;
1737
}
1738
1739
/**
1740
 * @param int  $course_id
1741
 * @param int  $thread_id
1742
 * @param int  $forum_id
1743
 * @param bool $show_visible
1744
 *
1745
 * @return array|bool
1746
 */
1747
function get_last_post_by_thread($course_id, $thread_id, $forum_id, $show_visible = true)
1748
{
1749
    if (empty($thread_id) || empty($forum_id) || empty($course_id)) {
1750
        return false;
1751
    }
1752
1753
    $thread_id = (int) $thread_id;
1754
    $forum_id = (int) $forum_id;
1755
    $course_id = (int) $course_id;
1756
1757
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1758
    $sql = "SELECT * FROM $table_posts
1759
            WHERE
1760
                c_id = $course_id AND
1761
                thread_id = $thread_id AND
1762
                forum_id = $forum_id";
1763
1764
    if (false == $show_visible) {
1765
        $sql .= ' AND visible = 1 ';
1766
    }
1767
1768
    $sql .= ' ORDER BY post_id DESC LIMIT 1';
1769
    $result = Database::query($sql);
1770
    if (Database::num_rows($result)) {
1771
        return Database::fetch_array($result, 'ASSOC');
1772
    } else {
1773
        return false;
1774
    }
1775
}
1776
1777
/**
1778
 * This function gets all the last post information of a certain forum.
1779
 *
1780
 * @param int    $forum_id        the id of the forum we want to know the last post information of
1781
 * @param bool   $show_invisibles
1782
 * @param string $course_id       course db name
1783
 * @param int    $sessionId       Optional. The session id
1784
 *
1785
 * @return array containing all the information about the last post
1786
 *               (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname,
1787
 *               last_poster_firstname)
1788
 *
1789
 * @author Patrick Cool <[email protected]>, Ghent University
1790
 *
1791
 * @version february 2006, dokeos 1.8
1792
 */
1793
function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null, $sessionId = 0)
1794
{
1795
    if (!isset($course_id)) {
1796
        $course_id = api_get_course_int_id();
1797
    } else {
1798
        $course_id = (int) $course_id;
1799
    }
1800
    $sessionId = $sessionId ? (int) $sessionId : api_get_session_id();
1801
1802
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1803
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1804
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1805
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1806
1807
    $forum_id = (int) $forum_id;
1808
    $return_array = [];
1809
1810
    // First get the threads to make sure there is no inconsistency in the
1811
    // database between forum and thread
1812
    $sql = "SELECT thread_id FROM $table_threads
1813
            WHERE
1814
                forum_id = $forum_id AND
1815
                c_id = $course_id AND
1816
                session_id = $sessionId";
1817
    $result = Database::query($sql);
1818
    if (0 == Database::num_rows($result)) {
1819
        // If there are no threads in this forum, then there are no posts
1820
        return [];
1821
    }
1822
    $threads = [];
1823
    while ($row = Database::fetch_row($result)) {
1824
        $threads[] = $row[0];
1825
    }
1826
    $threadsList = implode(',', $threads);
1827
    // Now get the posts that are linked to these threads
1828
    $sql = "SELECT
1829
                post.post_id,
1830
                post.forum_id,
1831
                post.poster_id,
1832
                post.poster_name,
1833
                post.post_date,
1834
                users.lastname,
1835
                users.firstname,
1836
                post.visible,
1837
                thread_properties.visibility AS thread_visibility,
1838
                forum_properties.visibility AS forum_visibility,
1839
                post.post_title,
1840
                post.post_text
1841
            FROM
1842
                $table_posts post,
1843
                $table_users users,
1844
                $table_item_property thread_properties,
1845
                $table_item_property forum_properties
1846
            WHERE
1847
                post.forum_id = $forum_id
1848
                AND post.thread_id IN ($threadsList)
1849
                AND post.poster_id = users.user_id
1850
                AND post.thread_id = thread_properties.ref
1851
                AND thread_properties.tool='".TOOL_FORUM_THREAD."'
1852
                AND post.forum_id=forum_properties.ref
1853
                AND forum_properties.tool='".TOOL_FORUM."'
1854
                AND post.c_id = $course_id AND
1855
                thread_properties.c_id = $course_id AND
1856
                forum_properties.c_id = $course_id
1857
            ORDER BY post.post_id DESC";
1858
    $result = Database::query($sql);
1859
1860
    if ($show_invisibles) {
1861
        $row = Database::fetch_array($result);
1862
        $return_array['last_post_id'] = $row['post_id'];
1863
        $return_array['last_poster_id'] = $row['poster_id'];
1864
        $return_array['last_post_date'] = $row['post_date'];
1865
        $return_array['last_poster_name'] = $row['poster_name'];
1866
        $return_array['last_poster_lastname'] = $row['lastname'];
1867
        $return_array['last_poster_firstname'] = $row['firstname'];
1868
        $return_array['last_post_title'] = $row['post_title'];
1869
        $return_array['last_post_text'] = $row['post_text'];
1870
1871
        return $return_array;
1872
    } else {
1873
        // We have to loop through the results to find the first one that is
1874
        // actually visible to students (forum_category, forum, thread AND post are visible).
1875
        while ($row = Database::fetch_array($result)) {
1876
            if ('1' == $row['visible'] && '1' == $row['thread_visibility'] && '1' == $row['forum_visibility']) {
1877
                $return_array['last_post_id'] = $row['post_id'];
1878
                $return_array['last_poster_id'] = $row['poster_id'];
1879
                $return_array['last_post_date'] = $row['post_date'];
1880
                $return_array['last_poster_name'] = $row['poster_name'];
1881
                $return_array['last_poster_lastname'] = $row['lastname'];
1882
                $return_array['last_poster_firstname'] = $row['firstname'];
1883
                $return_array['last_post_title'] = $row['post_title'];
1884
                $return_array['last_post_text'] = $row['post_text'];
1885
1886
                return $return_array;
1887
            }
1888
        }
1889
    }
1890
}
1891
1892
/**
1893
 * Retrieve all the threads of a given forum.
1894
 *
1895
 * @param int      $forum_id
1896
 * @param int|null $courseId  Optional If is null then it is considered the current course
1897
 * @param int|null $sessionId Optional. If is null then it is considered the current session
1898
 *
1899
 * @return CForumThread[]
1900
 */
1901
function get_threads($forumId, $courseId = null, $sessionId = null)
1902
{
1903
    $repo = Container::getForumThreadRepository();
1904
    $courseId = empty($courseId) ? api_get_course_int_id() : $courseId;
1905
    $course = api_get_course_entity($courseId);
1906
    $session = api_get_session_entity($sessionId);
1907
1908
    $qb = $repo->getResourcesByCourse($course, $session);
1909
1910
    $qb->andWhere('resource.forum = :forum')->setParameter('forum', $forumId);
1911
1912
    return $qb->getQuery()->getResult();
1913
1914
    $groupId = api_get_group_id();
0 ignored issues
show
Unused Code introduced by
$groupId = api_get_group_id() is not reachable.

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

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

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

    return false;
}

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

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