Passed
Push — master ( 891151...7b6b24 )
by Julito
12:45
created

getPosts()   F

Complexity

Conditions 14
Paths 432

Size

Total Lines 117
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

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