Passed
Push — master ( 268dc8...4a1618 )
by Julito
11:22
created

move_up_down()   C

Complexity

Conditions 14
Paths 163

Size

Total Lines 87
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 60
nc 163
nop 3
dl 0
loc 87
rs 5.7416
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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