Passed
Push — master ( ea0e05...21d25a )
by Julito
08:49
created

getPosts()   C

Complexity

Conditions 13
Paths 240

Size

Total Lines 118
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 64
nc 240
nop 6
dl 0
loc 118
rs 5.0121
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\Course;
6
use Chamilo\CoreBundle\Entity\GradebookLink;
7
use Chamilo\CoreBundle\Entity\User;
8
use Chamilo\CoreBundle\Framework\Container;
9
use Chamilo\CourseBundle\Entity\CForumAttachment;
10
use Chamilo\CourseBundle\Entity\CForumCategory;
11
use Chamilo\CourseBundle\Entity\CForumForum;
12
use Chamilo\CourseBundle\Entity\CForumNotification;
13
use Chamilo\CourseBundle\Entity\CForumPost;
14
use Chamilo\CourseBundle\Entity\CForumThread;
15
use Chamilo\CourseBundle\Entity\CGroup;
16
use Chamilo\CourseBundle\Entity\CLp;
17
use ChamiloSession as Session;
18
use Doctrine\Common\Collections\Criteria;
19
use Symfony\Component\HttpFoundation\File\UploadedFile;
20
21
/**
22
 * These files are a complete rework of the forum. The database structure is
23
 * based on phpBB but all the code is rewritten. A lot of new functionalities
24
 * are added:
25
 * - forum categories and forums can be sorted up or down, locked or made invisible
26
 * - consistent and integrated forum administration
27
 * - forum options:     are students allowed to edit their post?
28
 *                         moderation of posts (approval)
29
 *                         reply only forums (students cannot create new threads)
30
 *                         multiple forums per group
31
 * - sticky messages
32
 * - new view option: nested view
33
 * - quoting a message.
34
 *
35
 * @todo convert into a class
36
 */
37
/*define('FORUM_NEW_POST', 0);
38
getNotificationsPerUser();*/
39
40
function handleForum($url)
41
{
42
    $id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : null;
43
44
    if (api_is_allowed_to_edit(false, true)) {
45
        //if is called from a learning path lp_id
46
        $lp_id = isset($_REQUEST['lp_id']) ? (int) $_REQUEST['lp_id'] : null;
47
        $content = isset($_REQUEST['content']) ? $_REQUEST['content'] : '';
48
        $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
49
        $repo = null;
50
        switch ($content) {
51
            case 'forumcategory':
52
                $repo = Container::getForumCategoryRepository();
53
                break;
54
            case 'forum':
55
                $repo = Container::getForumRepository();
56
                break;
57
            case 'thread':
58
                $repo = Container::getForumThreadRepository();
59
                break;
60
        }
61
62
        $resource = null;
63
        if ($repo && $id) {
64
            $resource = $repo->find($id);
65
        }
66
67
        switch ($action) {
68
            case 'add_forum':
69
                $formContent = forumForm(null, $lp_id);
70
71
                return $formContent;
72
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

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