Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

show_add_forum_form()   F

Complexity

Conditions 34
Paths > 20000

Size

Total Lines 209
Code Lines 147

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 34
eloc 147
nc 14159232
nop 2
dl 0
loc 209
rs 2
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
/* For licensing terms, see /license.txt */
3
4
use ChamiloSession as Session;
5
use Doctrine\Common\Collections\Criteria;
6
use Chamilo\CourseBundle\Entity\CForumPost;
7
use Chamilo\CourseBundle\Entity\CForumThread;
8
use Chamilo\UserBundle\Entity\User;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, User. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
10
/**
11
 * These files are a complete rework of the forum. The database structure is
12
 * based on phpBB but all the code is rewritten. A lot of new functionalities
13
 * are added:
14
 * - forum categories and forums can be sorted up or down, locked or made invisible
15
 * - consistent and integrated forum administration
16
 * - forum options:     are students allowed to edit their post?
17
 *                         moderation of posts (approval)
18
 *                         reply only forums (students cannot create new threads)
19
 *                         multiple forums per group
20
 * - sticky messages
21
 * - new view option: nested view
22
 * - quoting a message
23
 *
24
 * @package chamilo.forum
25
 * @todo convert into a class
26
 */
27
28
define('FORUM_NEW_POST', 0);
29
get_notifications_of_user();
30
31
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
32
$htmlHeadXtra[] = '<script>
33
34
function check_unzip() {
35
    if (document.upload.unzip.checked){
36
        document.upload.if_exists[0].disabled=true;
37
        document.upload.if_exists[1].checked=true;
38
        document.upload.if_exists[2].disabled=true;
39
    } else {
40
        document.upload.if_exists[0].checked=true;
41
        document.upload.if_exists[0].disabled=false;
42
        document.upload.if_exists[2].disabled=false;
43
    }
44
}
45
function setFocus() {
46
    $("#title_file").focus();
47
}
48
</script>';
49
// The next javascript script is to manage ajax upload file
50
$htmlHeadXtra[] = api_get_jquery_libraries_js(['jquery-ui', 'jquery-upload']);
51
52
// Recover Thread ID, will be used to generate delete attachment URL to do ajax
53
$threadId = isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : 0;
54
$forumId = isset($_REQUEST['forum']) ? intval($_REQUEST['forum']) : 0;
55
56
// The next javascript script is to delete file by ajax
57
$htmlHeadXtra[] = '<script>
58
$(function () {
59
    $(document).on("click", ".deleteLink", function(e) {
60
        e.preventDefault();
61
        e.stopPropagation();
62
        var l = $(this);
63
        var id = l.closest("tr").attr("id");
64
        var filename = l.closest("tr").find(".attachFilename").html();
65
        if (confirm("' . get_lang('AreYouSureToDeleteJS').'", filename)) {
66
            $.ajax({
67
                type: "POST",
68
                url: "'.api_get_path(WEB_AJAX_PATH).'forum.ajax.php?'.api_get_cidreq().'&a=delete_file&attachId=" + id +"&thread='.$threadId.'&forum='.$forumId.'",
69
                dataType: "json",
70
                success: function(data) {
71
                    if (data.error == false) {
72
                        l.closest("tr").remove();
73
                        if ($(".files td").length < 1) {
74
                            $(".files").closest(".control-group").hide();
75
                        }
76
                    }
77
                }
78
            })
79
        }
80
    });
81
});
82
</script>';
83
84
/**
85
 * This function handles all the forum and forum categories actions. This is a wrapper for the
86
 * forum and forum categories. All this code code could go into the section where this function is
87
 * called but this make the code there cleaner.
88
 * @param int $lp_id Learning path Id
89
 *
90
 * @return void
91
 * @author Patrick Cool <[email protected]>, Ghent University
92
 * @author Juan Carlos Raña Trabado (return to lp_id)
93
 * @version may 2011, Chamilo 1.8.8
94
 */
95
function handle_forum_and_forumcategories($lp_id = null)
96
{
97
    $action_forum_cat = isset($_GET['action']) ? $_GET['action'] : '';
98
    $get_content = isset($_GET['content']) ? $_GET['content'] : '';
99
    $post_submit_cat = isset($_POST['SubmitForumCategory']) ? true : false;
100
    $post_submit_forum = isset($_POST['SubmitForum']) ? true : false;
101
    $get_id = isset($_GET['id']) ? intval($_GET['id']) : '';
102
    $forum_categories_list = get_forum_categories();
103
104
    //Verify if forum category exists
105
    if (empty($forum_categories_list)) {
106
        $get_content = 'forumcategory';
107
    }
108
109
    $content = '';
110
111
    // Adding a forum category
112
    if (($action_forum_cat == 'add' && $get_content == 'forumcategory') || $post_submit_cat) {
113
        $content = show_add_forumcategory_form([], $lp_id); //$lp_id when is called from learning path
114
    }
115
116
    // Adding a forum
117
    if ((($action_forum_cat == 'add' || $action_forum_cat == 'edit') && $get_content == 'forum') ||
118
        $post_submit_forum
119
    ) {
120
        if ($action_forum_cat == 'edit' && $get_id || $post_submit_forum) {
121
            $inputvalues = get_forums($get_id);
0 ignored issues
show
Bug introduced by
It seems like $get_id can also be of type string; however, parameter $id of get_forums() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

121
            $inputvalues = get_forums(/** @scrutinizer ignore-type */ $get_id);
Loading history...
122
        } else {
123
            $inputvalues = [];
124
        }
125
        $content = show_add_forum_form($inputvalues, $lp_id);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $content is correct as show_add_forum_form($inputvalues, $lp_id) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
126
    }
127
128
    // Edit a forum category
129
    if (($action_forum_cat == 'edit' && $get_content == 'forumcategory') ||
130
        (isset($_POST['SubmitEditForumCategory'])) ? true : false
131
    ) {
132
        $forum_category = get_forum_categories($get_id);
133
        $content = show_edit_forumcategory_form($forum_category);
134
    }
135
136
    // Delete a forum category
137
    if ($action_forum_cat == 'delete') {
138
        $id_forum = intval($get_id);
139
        $list_threads = get_threads($id_forum);
140
141
        for ($i = 0; $i < count($list_threads); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
142
            deleteForumCategoryThread('thread', $list_threads[$i]['thread_id']);
143
            $link_info = GradebookUtils::isResourceInCourseGradebook(
144
                api_get_course_id(),
145
                5,
146
                $list_threads[$i]['thread_id'],
147
                api_get_session_id()
148
            );
149
            if ($link_info !== false) {
150
                GradebookUtils::remove_resource_from_course_gradebook($link_info['id']);
151
            }
152
        }
153
        deleteForumCategoryThread($get_content, $get_id);
154
    }
155
156
    // Change visibility of a forum or a forum category.
157
    if ($action_forum_cat == 'invisible' || $action_forum_cat == 'visible') {
158
        $return_message = change_visibility($get_content, $get_id, $action_forum_cat);
0 ignored issues
show
Bug introduced by
It seems like $get_id can also be of type string; however, parameter $id of change_visibility() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

158
        $return_message = change_visibility($get_content, /** @scrutinizer ignore-type */ $get_id, $action_forum_cat);
Loading history...
159
        Display::addFlash(
160
            Display::return_message($return_message, 'confirmation', false)
161
        );
162
    }
163
    // Change lock status of a forum or a forum category.
164
    if ($action_forum_cat == 'lock' || $action_forum_cat == 'unlock') {
165
        $return_message = change_lock_status($get_content, $get_id, $action_forum_cat);
0 ignored issues
show
Bug introduced by
It seems like $get_id can also be of type string; however, parameter $id of change_lock_status() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
        $return_message = change_lock_status($get_content, /** @scrutinizer ignore-type */ $get_id, $action_forum_cat);
Loading history...
166
        Display::addFlash(
167
            Display::return_message($return_message, 'confirmation', false)
168
        );
169
    }
170
    // Move a forum or a forum category.
171
    if ($action_forum_cat == 'move' && isset($_GET['direction'])) {
172
        $return_message = move_up_down($get_content, $_GET['direction'], $get_id);
173
        Display::addFlash(
174
            Display::return_message($return_message, 'confirmation', false)
175
        );
176
    }
177
    return $content;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $content returns the type string which is incompatible with the documented return type void.
Loading history...
178
}
179
180
/**
181
 * This function displays the form that is used to add a forum category.
182
 *
183
 * @param  array $inputvalues (deprecated, set to null when calling)
184
 * @param  int $lp_id Learning path ID
185
 * @return string
186
 *
187
 * @author Patrick Cool <[email protected]>, Ghent University
188
 * @author Juan Carlos Raña Trabado (return to lp_id)
189
 * @version may 2011, Chamilo 1.8.8
190
 */
191
function show_add_forumcategory_form($inputvalues = [], $lp_id)
192
{
193
    $form = new FormValidator(
194
        'forumcategory',
195
        'post',
196
        'index.php?'.api_get_cidreq()
197
    );
198
    // hidden field if from learning path
199
    $form->addElement('hidden', 'lp_id', $lp_id);
200
    // Setting the form elements.
201
    $form->addElement('header', get_lang('AddForumCategory'));
202
    $form->addElement('text', 'forum_category_title', get_lang('Title'), ['autofocus']);
203
    $form->addElement(
204
        'html_editor',
205
        'forum_category_comment',
206
        get_lang('Description'),
207
        null,
208
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
209
    );
210
    $form->addButtonCreate(get_lang('CreateCategory'), 'SubmitForumCategory');
211
212
    // Setting the rules.
213
    $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
214
215
    // The validation or display
216
    if ($form->validate()) {
217
        $check = Security::check_token('post');
218
        if ($check) {
219
            $values = $form->exportValues();
220
            store_forumcategory($values);
221
        }
222
        Security::clear_token();
223
    } else {
224
        $token = Security::get_token();
225
        $form->addElement('hidden', 'sec_token');
226
        $form->setConstants(['sec_token' => $token]);
227
        return $form->returnForm();
228
    }
229
}
230
231
/**
232
 * This function displays the form that is used to add a forum category.
233
 *
234
 * @param array $inputvalues
235
 * @param int $lp_id
236
 * @return void HTML
237
 *
238
 * @author Patrick Cool <[email protected]>, Ghent University
239
 * @author Juan Carlos Raña Trabado (return to lp_id)
240
 *
241
 * @version may 2011, Chamilo 1.8.8
242
 */
243
function show_add_forum_form($inputvalues = [], $lp_id)
244
{
245
    $_course = api_get_course_info();
246
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq());
247
248
    // The header for the form
249
    if (!empty($inputvalues)) {
250
        $form_title = get_lang('EditForum');
251
    } else {
252
        $form_title = get_lang('AddForum');
253
    }
254
255
    $form->addElement('header', $form_title);
256
257
    // We have a hidden field if we are editing.
258
    if (!empty($inputvalues) && is_array($inputvalues)) {
259
        $my_forum_id = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
260
        $form->addElement('hidden', 'forum_id', $my_forum_id);
261
    }
262
    $lp_id = intval($lp_id);
263
264
    // hidden field if from learning path
265
    $form->addElement('hidden', 'lp_id', $lp_id);
266
267
    // The title of the forum
268
    $form->addElement('text', 'forum_title', get_lang('Title'), ['autofocus']);
269
270
    // The comment of the forum.
271
    $form->addElement(
272
        'html_editor',
273
        'forum_comment',
274
        get_lang('Description'),
275
        null,
276
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
277
    );
278
279
    // Dropdown list: Forum categories
280
    $forum_categories = get_forum_categories();
281
    foreach ($forum_categories as $key => $value) {
282
        $forum_categories_titles[$value['cat_id']] = $value['cat_title'];
283
    }
284
    $form->addElement(
285
        'select',
286
        'forum_category',
287
        get_lang('InForumCategory'),
288
        $forum_categories_titles
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $forum_categories_titles seems to be defined by a foreach iteration on line 281. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
289
    );
290
    $form->applyFilter('forum_category', 'html_filter');
291
292
    if ($_course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD) {
293
        // This is for horizontal
294
        $group = [];
295
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('Yes'), 1);
296
        $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('No'), 0);
297
        $form->addGroup($group, 'allow_anonymous_group', get_lang('AllowAnonymousPosts'));
298
    }
299
300
    $form->addButtonAdvancedSettings('advanced_params');
301
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
302
303
    $form->addDateTimePicker(
304
        'start_time',
305
        [get_lang('ForumStartDate'), get_lang('ForumStartDateComment')],
306
        ['id' => 'start_time']
307
    );
308
309
    $form->addDateTimePicker(
310
        'end_time',
311
        [get_lang('ForumEndDate'), get_lang('ForumEndDateComment')],
312
        ['id' => 'end_time']
313
    );
314
315
    $form->addRule(
316
        ['start_time', 'end_time'],
317
        get_lang('StartDateMustBeBeforeTheEndDate'),
318
        'compare_datetime_text',
319
        '< allow_empty'
320
    );
321
322
    $group = [];
323
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('Yes'), 1);
324
    $group[] = $form->createElement('radio', 'moderated', null, get_lang('No'), 0);
325
    $form->addGroup($group, 'moderated', get_lang('ModeratedForum'));
326
327
    $group = [];
328
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('Yes'), 1);
329
    $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('No'), 0);
330
    $form->addGroup($group, 'students_can_edit_group', get_lang('StudentsCanEdit'));
331
332
    $group = [];
333
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Approval'), 1);
334
    $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Direct'), 0);
335
336
    $group = [];
337
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('Yes'), 1);
338
    $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('No'), 0);
339
340
    $group = [];
341
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('Yes'), 1);
342
    $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('No'), 0);
343
    $form->addGroup($group, 'allow_new_threads_group', get_lang('AllowNewThreads'));
344
345
    $group = [];
346
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
347
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
348
    $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
349
    $form->addGroup($group, 'default_view_type_group', get_lang('DefaultViewType'));
350
351
    // Drop down list: Groups
352
    $groups = GroupManager::get_group_list();
353
    $groups_titles[0] = get_lang('NotAGroupForum');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$groups_titles was never initialized. Although not strictly required by PHP, it is generally a good practice to add $groups_titles = array(); before regardless.
Loading history...
354
    foreach ($groups as $key => $value) {
355
        $groups_titles[$value['id']] = $value['name'];
356
    }
357
    $form->addElement('select', 'group_forum', get_lang('ForGroup'), $groups_titles);
358
359
    // Public or private group forum
360
    $group = [];
361
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Public'), 'public');
362
    $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Private'), 'private');
363
    $form->addGroup($group, 'public_private_group_forum_group', get_lang('PublicPrivateGroupForum'));
364
365
    // Forum image
366
    $form->addProgress();
367
    if (!empty($inputvalues['forum_image'])) {
368
        $baseImagePath = api_get_course_path().'/upload/forum/images/'.$inputvalues['forum_image'];
369
        $image_path = api_get_path(WEB_COURSE_PATH).$baseImagePath;
370
        $sysImagePath = api_get_path(SYS_COURSE_PATH).$baseImagePath;
371
372
        if (file_exists($sysImagePath)) {
373
            $show_preview_image = Display::img(
374
                $image_path,
375
                null,
376
                ['class' => 'img-responsive']
377
            );
378
            $form->addElement('label', get_lang('PreviewImage'), $show_preview_image);
379
            $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
380
        }
381
    }
382
    $forum_image = isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
383
    $form->addElement('file', 'picture', ($forum_image != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
384
    $form->addRule(
385
        'picture',
386
        get_lang('OnlyImagesAllowed'),
387
        'filetype',
388
        ['jpg', 'jpeg', 'png', 'gif']
389
    );
390
    $form->addElement('html', '</div>');
391
392
    // The OK button
393
    if (isset($_GET['id']) && $_GET['action'] == 'edit') {
394
        $form->addButtonUpdate(get_lang('ModifyForum'), 'SubmitForum');
395
    } else {
396
        $form->addButtonCreate(get_lang('CreateForum'), 'SubmitForum');
397
    }
398
399
    // setting the rules
400
    $form->addRule('forum_title', get_lang('ThisFieldIsRequired'), 'required');
401
    $form->addRule('forum_category', get_lang('ThisFieldIsRequired'), 'required');
402
403
    $defaultSettingAllowNewThreads = api_get_default_tool_setting('forum', 'allow_new_threads', 0);
404
405
    // Settings the defaults
406
    if (empty($inputvalues) || !is_array($inputvalues)) {
407
        $defaults['moderated']['moderated'] = 0;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$defaults was never initialized. Although not strictly required by PHP, it is generally a good practice to add $defaults = array(); before regardless.
Loading history...
408
        $defaults['allow_anonymous_group']['allow_anonymous'] = 0;
409
        $defaults['students_can_edit_group']['students_can_edit'] = 0;
410
        $defaults['approval_direct_group']['approval_direct'] = 0;
411
        $defaults['allow_attachments_group']['allow_attachments'] = 1;
412
        $defaults['allow_new_threads_group']['allow_new_threads'] = $defaultSettingAllowNewThreads;
413
        $defaults['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
414
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = 'public';
415
        if (isset($_GET['forumcategory'])) {
416
            $defaults['forum_category'] = Security::remove_XSS($_GET['forumcategory']);
417
        }
418
    } else {
419
        // the default values when editing = the data in the table
420
        $defaults['forum_id'] = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
421
        $defaults['forum_title'] = prepare4display(isset($inputvalues['forum_title']) ? $inputvalues['forum_title'] : null);
422
        $defaults['forum_comment'] = prepare4display(isset($inputvalues['forum_comment']) ? $inputvalues['forum_comment'] : null);
423
        $defaults['start_time'] = isset($inputvalues['start_time']) ? api_get_local_time($inputvalues['start_time']) : null;
424
        $defaults['end_time'] = isset($inputvalues['end_time']) ? api_get_local_time($inputvalues['end_time']) : null;
425
        $defaults['moderated']['moderated'] = isset($inputvalues['moderated']) ? $inputvalues['moderated'] : 0;
426
        $defaults['forum_category'] = isset($inputvalues['forum_category']) ? $inputvalues['forum_category'] : null;
427
        $defaults['allow_anonymous_group']['allow_anonymous'] = isset($inputvalues['allow_anonymous']) ? $inputvalues['allow_anonymous'] : null;
428
        $defaults['students_can_edit_group']['students_can_edit'] = isset($inputvalues['allow_edit']) ? $inputvalues['allow_edit'] : null;
429
        $defaults['approval_direct_group']['approval_direct'] = isset($inputvalues['approval_direct_post']) ? $inputvalues['approval_direct_post'] : null;
430
        $defaults['allow_attachments_group']['allow_attachments'] = isset($inputvalues['allow_attachments']) ? $inputvalues['allow_attachments'] : null;
431
        $defaults['allow_new_threads_group']['allow_new_threads'] = isset($inputvalues['allow_new_threads']) ? $inputvalues['allow_new_threads'] : $defaultSettingAllowNewThreads;
432
        $defaults['default_view_type_group']['default_view_type'] = isset($inputvalues['default_view']) ? $inputvalues['default_view'] : null;
433
        $defaults['public_private_group_forum_group']['public_private_group_forum'] = isset($inputvalues['forum_group_public_private']) ? $inputvalues['forum_group_public_private'] : null;
434
        $defaults['group_forum'] = isset($inputvalues['forum_of_group']) ? $inputvalues['forum_of_group'] : null;
435
    }
436
    $form->setDefaults($defaults);
437
    // Validation or display
438
    if ($form->validate()) {
439
        $check = Security::check_token('post');
440
        if ($check) {
441
            $values = $form->getSubmitValues();
442
            $return_message = store_forum($values);
443
            Display::addFlash(Display::return_message($return_message, 'confirmation'));
444
        }
445
        Security::clear_token();
446
    } else {
447
        $token = Security::get_token();
448
        $form->addElement('hidden', 'sec_token');
449
        $form->setConstants(['sec_token' => $token]);
450
451
        return $form->returnForm();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $form->returnForm() returns the type string which is incompatible with the documented return type void.
Loading history...
452
    }
453
}
454
455
/**
456
 * This function deletes the forum image if exists
457
 *
458
 * @param int forum id
459
 * @return boolean true if success
460
 * @author Julio Montoya <[email protected]>
461
 * @version february 2006, dokeos 1.8
462
 */
463
function delete_forum_image($forum_id)
464
{
465
    $table_forums = Database::get_course_table(TABLE_FORUM);
466
    $course_id = api_get_course_int_id();
467
    $forum_id = intval($forum_id);
468
469
    $sql = "SELECT forum_image FROM $table_forums
470
            WHERE forum_id = $forum_id AND c_id = $course_id";
471
    $result = Database::query($sql);
472
    $row = Database::fetch_array($result);
473
    if ($row['forum_image'] != '') {
474
        $file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
475
        if (file_exists($file)) {
476
            unlink($file);
477
        }
478
479
        return true;
480
    } else {
481
        return false;
482
    }
483
}
484
485
/**
486
 * This function displays the form that is used to edit a forum category.
487
 *
488
 * @param array
489
 * @return string
490
 *
491
 * @author Patrick Cool <[email protected]>, Ghent University
492
 * @version february 2006, dokeos 1.8
493
 */
494
function show_edit_forumcategory_form($inputvalues = [])
495
{
496
    $categoryId = $inputvalues['cat_id'];
497
    $form = new FormValidator('forumcategory', 'post', 'index.php?'.api_get_cidreq().'&id='.$categoryId);
498
499
    // Setting the form elements.
500
    $form->addElement('header', '', get_lang('EditForumCategory'));
501
    $form->addElement('hidden', 'forum_category_id');
502
    $form->addElement('text', 'forum_category_title', get_lang('Title'));
503
504
    $form->addElement(
505
        'html_editor',
506
        'forum_category_comment',
507
        get_lang('Comment'),
508
        null,
509
        ['ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200']
510
    );
511
512
    $form->addButtonUpdate(get_lang('ModifyCategory'), 'SubmitEditForumCategory');
513
514
    // Setting the default values.
515
    $defaultvalues['forum_category_id'] = $inputvalues['cat_id'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$defaultvalues was never initialized. Although not strictly required by PHP, it is generally a good practice to add $defaultvalues = array(); before regardless.
Loading history...
516
    $defaultvalues['forum_category_title'] = $inputvalues['cat_title'];
517
    $defaultvalues['forum_category_comment'] = $inputvalues['cat_comment'];
518
    $form->setDefaults($defaultvalues);
519
520
    // Setting the rules.
521
    $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
522
523
    // Validation or display
524
    if ($form->validate()) {
525
        $check = Security::check_token('post');
526
        if ($check) {
527
            $values = $form->exportValues();
528
            store_forumcategory($values);
529
        }
530
        Security::clear_token();
531
    } else {
532
        $token = Security::get_token();
533
        $form->addElement('hidden', 'sec_token');
534
        $form->setConstants(['sec_token' => $token]);
535
        return $form->returnForm();
536
    }
537
}
538
539
/**
540
 * This function stores the forum category in the database.
541
 * The new category is added to the end.
542
 *
543
 * @param array $values
544
 * @param array $courseInfo
545
 * @param bool $showMessage
546
 * @return void HMTL language variable
547
 *
548
 * @author Patrick Cool <[email protected]>, Ghent University
549
 * @version february 2006, dokeos 1.8
550
 */
551
function store_forumcategory($values, $courseInfo = [], $showMessage = true)
552
{
553
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
554
    $course_id = $courseInfo['real_id'];
555
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
556
557
    // Find the max cat_order. The new forum category is added at the end => max cat_order + &
558
    $sql = "SELECT MAX(cat_order) as sort_max
559
            FROM $table_categories
560
            WHERE c_id = $course_id";
561
    $result = Database::query($sql);
562
    $row = Database::fetch_array($result);
563
    $new_max = $row['sort_max'] + 1;
564
    $session_id = api_get_session_id();
565
    $clean_cat_title = $values['forum_category_title'];
566
    $last_id = null;
567
568
    if (isset($values['forum_category_id'])) {
569
        // Storing after edition.
570
        $params = [
571
            'cat_title' => $clean_cat_title,
572
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
573
        ];
574
575
        Database::update(
576
            $table_categories,
577
            $params,
578
            [
579
                'c_id = ? AND cat_id = ?' => [
580
                    $course_id,
581
                    $values['forum_category_id'],
582
                ],
583
            ]
584
        );
585
586
        api_item_property_update(
587
            $courseInfo,
588
            TOOL_FORUM_CATEGORY,
589
            $values['forum_category_id'],
590
            'ForumCategoryUpdated',
591
            api_get_user_id()
592
        );
593
        $return_message = get_lang('ForumCategoryEdited');
594
    } else {
595
        $params = [
596
            'c_id' => $course_id,
597
            'cat_title' => $clean_cat_title,
598
            'cat_comment' => isset($values['forum_category_comment']) ? $values['forum_category_comment'] : '',
599
            'cat_order' => $new_max,
600
            'session_id' => $session_id,
601
            'locked' => 0,
602
            'cat_id' => 0
603
        ];
604
        $last_id = Database::insert($table_categories, $params);
605
606
        if ($last_id > 0) {
607
            $sql = "UPDATE $table_categories SET cat_id = $last_id WHERE iid = $last_id";
608
            Database::query($sql);
609
610
            api_item_property_update(
611
                $courseInfo,
612
                TOOL_FORUM_CATEGORY,
613
                $last_id,
0 ignored issues
show
Bug introduced by
It seems like $last_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

613
                /** @scrutinizer ignore-type */ $last_id,
Loading history...
614
                'ForumCategoryAdded',
615
                api_get_user_id()
616
            );
617
            api_set_default_visibility(
618
                $last_id,
0 ignored issues
show
Bug introduced by
It seems like $last_id can also be of type false; however, parameter $item_id of api_set_default_visibility() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

618
                /** @scrutinizer ignore-type */ $last_id,
Loading history...
619
                TOOL_FORUM_CATEGORY,
620
                0,
621
                $courseInfo
622
            );
623
        }
624
        $return_message = get_lang('ForumCategoryAdded');
625
    }
626
627
    if ($showMessage) {
628
        Display::addFlash(Display::return_message($return_message, 'confirmation'));
629
    }
630
631
    return $last_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $last_id also could return the type integer|false which is incompatible with the documented return type void.
Loading history...
632
}
633
634
/**
635
 * This function stores the forum in the database. The new forum is added to the end.
636
 *
637
 * @param array $values
638
 * @param array $courseInfo
639
 * @param bool  $returnId
640
 * @return string language variable
641
 *
642
 * @author Patrick Cool <[email protected]>, Ghent University
643
 * @version february 2006, dokeos 1.8
644
 */
645
function store_forum($values, $courseInfo = [], $returnId = false)
646
{
647
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
648
    $course_id = $courseInfo['real_id'];
649
    $session_id = api_get_session_id();
650
651
    if (isset($values['group_id']) && !empty($values['group_id'])) {
652
        $group_id = $values['group_id'];
653
    } else {
654
        $group_id = api_get_group_id();
655
    }
656
    $groupInfo = [];
657
    if (!empty($group_id)) {
658
        $groupInfo = GroupManager::get_group_properties($group_id);
659
    }
660
661
    $table_forums = Database::get_course_table(TABLE_FORUM);
662
663
    // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
664
    if (is_null($values['forum_category'])) {
665
        $new_max = null;
666
    } else {
667
        $sql = "SELECT MAX(forum_order) as sort_max
668
                FROM $table_forums
669
                WHERE
670
                    c_id = $course_id AND
671
                    forum_category='".Database::escape_string($values['forum_category'])."'";
672
        $result = Database::query($sql);
673
        $row = Database::fetch_array($result);
674
        $new_max = $row['sort_max'] + 1;
675
    }
676
677
    // Forum images
678
    $image_moved = false;
679
    $has_attachment = false;
680
    if (!empty($_FILES['picture']['name'])) {
681
        $upload_ok = process_uploaded_file($_FILES['picture']);
682
        $has_attachment = true;
683
    } else {
684
        $image_moved = true;
685
    }
686
687
    // Remove existing picture if it was requested.
688
    if (!empty($_POST['remove_picture'])) {
689
        delete_forum_image($values['forum_id']);
690
    }
691
692
    $new_file_name = '';
693
    if (isset($upload_ok)) {
694
        if ($has_attachment) {
695
            $course_dir = $courseInfo['path'].'/upload/forum/images';
696
            $sys_course_path = api_get_path(SYS_COURSE_PATH);
697
            $updir = $sys_course_path.$course_dir;
698
            // Try to add an extension to the file if it hasn't one.
699
            $new_file_name = add_ext_on_mime(
700
                Database::escape_string($_FILES['picture']['name']),
701
                $_FILES['picture']['type']
702
            );
703
            if (!filter_extension($new_file_name)) {
704
                //Display::addFlash(Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error'));
705
                $image_moved = false;
706
            } else {
707
                $file_extension = explode('.', $_FILES['picture']['name']);
708
                $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
0 ignored issues
show
Bug introduced by
The call to sizeof() has too few arguments starting with mode. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

708
                $file_extension = strtolower($file_extension[/** @scrutinizer ignore-call */ sizeof($file_extension) - 1]);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
709
                $new_file_name = uniqid('').'.'.$file_extension;
710
                $new_path = $updir.'/'.$new_file_name;
711
                $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
712
                // Storing the attachments if any
713
                if ($result) {
714
                    $image_moved = true;
715
                }
716
            }
717
        }
718
    }
719
720
    if (isset($values['forum_id'])) {
721
        // Storing after edition.
722
        $params = [
723
            'forum_title'=> $values['forum_title'],
724
            'forum_comment'=> isset($values['forum_comment']) ? $values['forum_comment'] : null,
725
            'forum_category'=> isset($values['forum_category']) ? $values['forum_category'] : null,
726
            'allow_anonymous'=> isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null,
727
            'allow_edit'=> isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null,
728
            'approval_direct_post'=> isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null,
729
            'allow_attachments'=> isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null,
730
            'allow_new_threads'=> isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null,
731
            'default_view'=> isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null,
732
            'forum_of_group'=> isset($values['group_forum']) ? $values['group_forum'] : null,
733
            'forum_group_public_private'=> isset($values['public_private_group_forum_group']['public_private_group_forum']) ? $values['public_private_group_forum_group']['public_private_group_forum'] : null,
734
            'moderated'=> $values['moderated']['moderated'],
735
            'start_time' => !empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null,
736
            'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
737
            'session_id'=> $session_id,
738
            'lp_id' => isset($values['lp_id']) ? intval($values['lp_id']) : 0
739
        ];
740
741
        if (isset($upload_ok)) {
742
            if ($has_attachment) {
743
                $params['forum_image'] = $new_file_name;
744
            }
745
        }
746
747
        if (isset($values['remove_picture']) && $values['remove_picture'] == 1) {
748
            $params['forum_image'] = '';
749
            delete_forum_image($values['forum_id']);
750
        }
751
752
        Database::update(
753
            $table_forums,
754
            $params,
755
            ['c_id = ? AND forum_id = ?' => [$course_id, $values['forum_id']]]
756
        );
757
758
        api_item_property_update(
759
            $courseInfo,
760
            TOOL_FORUM,
761
            Database::escape_string($values['forum_id']),
762
            'ForumUpdated',
763
            api_get_user_id(),
764
            $groupInfo
765
        );
766
767
        $return_message = get_lang('ForumEdited');
768
    } else {
769
        if ($image_moved) {
770
            $new_file_name = isset($new_file_name) ? $new_file_name : '';
771
        }
772
        $params = [
773
            'c_id' => $course_id,
774
            'forum_title'=> $values['forum_title'],
775
            'forum_image'=> $new_file_name,
776
            'forum_comment'=> isset($values['forum_comment']) ? $values['forum_comment'] : null,
777
            'forum_category'=> isset($values['forum_category']) ? $values['forum_category'] : null,
778
            'allow_anonymous'=> isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null,
779
            'allow_edit'=> isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null,
780
            'approval_direct_post'=> isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null,
781
            'allow_attachments'=> isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null,
782
            'allow_new_threads'=> isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null,
783
            'default_view'=> isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null,
784
            'forum_of_group'=> isset($values['group_forum']) ? $values['group_forum'] : null,
785
            'forum_group_public_private'=> isset($values['public_private_group_forum_group']['public_private_group_forum']) ? $values['public_private_group_forum_group']['public_private_group_forum'] : null,
786
            'moderated'=> isset($values['moderated']['moderated']) ? (int) $values['moderated']['moderated'] : 0,
787
            'start_time' => !empty($values['start_time']) ? api_get_utc_datetime($values['start_time']) : null,
788
            'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
789
            'forum_order'=> isset($new_max) ? $new_max : null,
790
            'session_id'=> $session_id,
791
            'lp_id' => isset($values['lp_id']) ? intval($values['lp_id']) : 0,
792
            'locked' => 0,
793
            'forum_id' => 0
794
        ];
795
796
        $last_id = Database::insert($table_forums, $params);
797
        if ($last_id > 0) {
798
            $sql = "UPDATE $table_forums SET forum_id = iid WHERE iid = $last_id";
799
            Database::query($sql);
800
801
            api_item_property_update(
802
                $courseInfo,
803
                TOOL_FORUM,
804
                $last_id,
0 ignored issues
show
Bug introduced by
It seems like $last_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

804
                /** @scrutinizer ignore-type */ $last_id,
Loading history...
805
                'ForumAdded',
806
                api_get_user_id(),
807
                $groupInfo
808
            );
809
810
            api_set_default_visibility(
811
                $last_id,
0 ignored issues
show
Bug introduced by
It seems like $last_id can also be of type false; however, parameter $item_id of api_set_default_visibility() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

811
                /** @scrutinizer ignore-type */ $last_id,
Loading history...
812
                TOOL_FORUM,
813
                $group_id,
814
                $courseInfo
815
            );
816
        }
817
        $return_message = get_lang('ForumAdded');
818
        if ($returnId) {
819
            return $last_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $last_id could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
820
        }
821
    }
822
823
    return $return_message;
824
}
825
826
/**
827
 * This function deletes a forum or a forum category
828
 * This function currently does not delete the forums inside the category,
829
 * nor the threads and replies inside these forums.
830
 * For the moment this is the easiest method and it has the advantage that it
831
 * allows to recover fora that were acidently deleted
832
 * when the forum category got deleted.
833
 *
834
 * @param $content = what we are deleting (a forum or a forum category)
835
 * @param $id The id of the forum category that has to be deleted.
836
 *
837
 * @todo write the code for the cascading deletion of the forums inside a
838
 * forum category and also the threads and replies inside these forums
839
 * @todo config setting for recovery or not
840
 * (see also the documents tool: real delete or not).
841
 * @return string
842
 * @author Patrick Cool <[email protected]>, Ghent University
843
 * @version february 2006, dokeos 1.8
844
 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment = at position 0 could not be parsed: Unknown type name '=' at position 0 in =.
Loading history...
845
function deleteForumCategoryThread($content, $id)
846
{
847
    $_course = api_get_course_info();
848
    $table_forums = Database::get_course_table(TABLE_FORUM);
849
    $table_forums_post = Database::get_course_table(TABLE_FORUM_POST);
850
    $table_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
851
    $course_id = api_get_course_int_id();
852
    $groupId = api_get_group_id();
853
    $groupInfo = GroupManager::get_group_properties($groupId);
854
    $userId = api_get_user_id();
855
    $id = intval($id);
856
857
    // Delete all attachment file about this tread id.
858
    $sql = "SELECT post_id FROM $table_forums_post
859
            WHERE c_id = $course_id AND thread_id = '".$id."' ";
860
    $res = Database::query($sql);
861
    while ($poster_id = Database::fetch_row($res)) {
862
        delete_attachment($poster_id[0]);
863
    }
864
865
    $tool_constant = null;
866
    $return_message = '';
867
    if ($content == 'forumcategory') {
868
        $tool_constant = TOOL_FORUM_CATEGORY;
869
        $return_message = get_lang('ForumCategoryDeleted');
870
871
        if (!empty($forum_list)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $forum_list does not exist. Did you maybe mean $forum_id?
Loading history...
872
            $sql = "SELECT forum_id FROM $table_forums
873
                    WHERE c_id = $course_id AND forum_category='".$id."'";
874
            $result = Database::query($sql);
875
            $row = Database::fetch_array($result);
876
            foreach ($row as $arr_forum) {
877
                $forum_id = $arr_forum['forum_id'];
878
                api_item_property_update(
879
                    $_course,
880
                    'forum',
881
                    $forum_id,
882
                    'delete',
883
                    api_get_user_id()
884
                );
885
            }
886
        }
887
    }
888
889
    if ($content == 'forum') {
890
        $tool_constant = TOOL_FORUM;
891
        $return_message = get_lang('ForumDeleted');
892
893
        if (!empty($number_threads)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $number_threads seems to never exist and therefore empty should always be true.
Loading history...
894
            $sql = "SELECT thread_id FROM $table_forum_thread 
895
                    WHERE c_id = $course_id AND forum_id = $id ";
896
            $result = Database::query($sql);
897
            $row = Database::fetch_array($result);
898
            foreach ($row as $arr_forum) {
899
                $forum_id = $arr_forum['thread_id'];
900
                api_item_property_update(
901
                    $_course,
902
                    'forum_thread',
903
                    $forum_id,
904
                    'delete',
905
                    api_get_user_id()
906
                );
907
            }
908
        }
909
    }
910
911
    if ($content == 'thread') {
912
        $tool_constant = TOOL_FORUM_THREAD;
913
        $return_message = get_lang('ThreadDeleted');
914
    }
915
916
    api_item_property_update(
917
        $_course,
918
        $tool_constant,
919
        $id,
920
        'delete',
921
        $userId,
922
        $groupInfo
923
    );
924
925
    // Check if this returns a true and if so => return $return_message, if not => return false;
926
    if (!empty($return_message)) {
927
        Display::addFlash(Display::return_message($return_message, 'confirmation', false));
928
    }
929
    return $return_message;
930
}
931
932
/**
933
 * This function deletes a forum post. This separate function is needed because forum posts do not appear in the item_property table (yet)
934
 * and because deleting a post also has consequence on the posts that have this post as parent_id (they are also deleted).
935
 * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
936
 * We also have to decrease the number of replies in the thread table
937
 *
938
 * @param $post_id the id of the post that will be deleted
939
 * @todo write recursive function that deletes all the posts that have this message as parent
940
 * @return string language variable
941
 * @author Patrick Cool <[email protected]>, Ghent University
942
 * @author Hubert Borderiou Function cleanead and fixed
943
 * @version february 2006
944
 */
945
function delete_post($post_id)
946
{
947
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
948
    $post_id = intval($post_id);
949
    $course_id = api_get_course_int_id();
950
    $em = Database::getManager();
951
952
    $post = $em
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $post is correct as $em->getRepository('Cham... 'postId' => $post_id)) targeting Doctrine\ORM\EntityRepository::findOneBy() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
953
        ->getRepository('ChamiloCourseBundle:CForumPost')
954
        ->findOneBy(['cId' => $course_id, 'postId' => $post_id]);
955
956
    if ($post) {
957
        $em
958
            ->createQuery('
959
                UPDATE ChamiloCourseBundle:CForumPost p
960
                SET p.postParentId = :parent_of_deleted_post
961
                WHERE
962
                    p.cId = :course AND
963
                    p.postParentId = :post AND
964
                    p.threadId = :thread_of_deleted_post AND
965
                    p.forumId = :forum_of_deleted_post
966
            ')
967
            ->execute([
968
                'parent_of_deleted_post' => $post->getPostParentId(),
969
                'course' => $course_id,
970
                'post' => $post->getPostId(),
971
                'thread_of_deleted_post' => $post->getThreadId(),
972
                'forum_of_deleted_post' => $post->getForumId()
973
            ]);
974
975
        $em->remove($post);
976
        $em->flush();
977
978
        // Delete attachment file about this post id.
979
        delete_attachment($post_id);
980
    }
981
982
    $last_post_of_thread = check_if_last_post_of_thread($_GET['thread']);
983
984
    if (is_array($last_post_of_thread)) {
985
        // Decreasing the number of replies for this thread and also changing the last post information.
986
        $sql = "UPDATE $table_threads
987
                SET
988
                    thread_replies = thread_replies - 1,
989
                    thread_last_post = ".intval($last_post_of_thread['post_id']).",
990
                    thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
991
                WHERE c_id = $course_id AND thread_id = ".intval($_GET['thread']);
992
        Database::query($sql);
993
994
        return 'PostDeleted';
995
    }
996
    if (!$last_post_of_thread) {
997
        // We deleted the very single post of the thread so we need to delete the entry in the thread table also.
998
        $sql = "DELETE FROM $table_threads
999
                WHERE c_id = $course_id AND thread_id = ".intval($_GET['thread']);
1000
        Database::query($sql);
1001
1002
        return 'PostDeletedSpecial';
1003
    }
1004
}
1005
1006
/**
1007
 * This function gets the all information of the last (=most recent) post of the thread
1008
 * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date
1009
 *
1010
 * @param $thread_id the id of the thread we want to know the last post of.
1011
 * @return an array or bool if there is a last post found, false if there is
1012
 * no post entry linked to that thread => thread will be deleted
1013
 *
1014
 * @author Patrick Cool <[email protected]>, Ghent University
1015
 * @version february 2006, dokeos 1.8
1016
 */
1017
function check_if_last_post_of_thread($thread_id)
1018
{
1019
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1020
    $course_id = api_get_course_int_id();
1021
    $sql = "SELECT * FROM $table_posts
1022
            WHERE c_id = $course_id AND thread_id = ".intval($thread_id)."
1023
            ORDER BY post_date DESC";
1024
    $result = Database::query($sql);
1025
    if (Database::num_rows($result) > 0) {
1026
        $row = Database::fetch_array($result);
1027
1028
        return $row;
1029
    } else {
1030
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type an.
Loading history...
1031
    }
1032
}
1033
1034
/**
1035
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1036
 * @param int $id the id of the content we want to make invisible
1037
 * @param int $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
1038
 * @param array $additional_url_parameters
1039
 *
1040
 * @return string HTML
1041
 */
1042
function return_visible_invisible_icon(
1043
    $content,
1044
    $id,
1045
    $current_visibility_status,
1046
    $additional_url_parameters = ''
1047
) {
1048
    $html = '';
1049
    $id = (int) $id;
1050
    $current_visibility_status = (int) $current_visibility_status;
1051
1052
    if ($current_visibility_status == 1) {
1053
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1054
        if (is_array($additional_url_parameters)) {
1055
            foreach ($additional_url_parameters as $key => $value) {
1056
                $html .= $key.'='.$value.'&';
1057
            }
1058
        }
1059
        $html .= 'action=invisible&content='.$content.'&id='.$id.'">'.
1060
            Display::return_icon('visible.png', get_lang('MakeInvisible'), [], ICON_SIZE_SMALL).'</a>';
1061
    }
1062
    if ($current_visibility_status == 0) {
1063
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1064
        if (is_array($additional_url_parameters)) {
1065
            foreach ($additional_url_parameters as $key => $value) {
1066
                $html .= $key.'='.$value.'&';
1067
            }
1068
        }
1069
        $html .= 'action=visible&content='.$content.'&id='.$id.'">'.
1070
            Display::return_icon('invisible.png', get_lang('MakeVisible'), [], ICON_SIZE_SMALL).'</a>';
1071
    }
1072
1073
    return $html;
1074
}
1075
1076
/**
1077
 * @param $content
1078
 * @param $id
1079
 * @param $current_lock_status
1080
 * @param string $additional_url_parameters
1081
 * @return string
1082
 */
1083
function return_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters = '')
1084
{
1085
    $html = '';
1086
    $id = intval($id);
1087
    //check if the forum is blocked due
1088
    if ($content == 'thread') {
1089
        if (api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD)) {
1090
            $html .= Display::return_icon(
1091
                'lock_na.png',
1092
                get_lang('ResourceLockedByGradebook'),
1093
                [],
1094
                ICON_SIZE_SMALL
1095
            );
1096
1097
            return $html;
1098
        }
1099
    }
1100
    if ($current_lock_status == '1') {
1101
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1102
        if (is_array($additional_url_parameters)) {
1103
            foreach ($additional_url_parameters as $key => $value) {
1104
                $html .= $key.'='.$value.'&';
1105
            }
1106
        }
1107
        $html .= 'action=unlock&content='.$content.'&id='.$id.'">'.
1108
            Display::return_icon('lock.png', get_lang('Unlock'), [], ICON_SIZE_SMALL).'</a>';
1109
    }
1110
    if ($current_lock_status == '0') {
1111
        $html .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
1112
        if (is_array($additional_url_parameters)) {
1113
            foreach ($additional_url_parameters as $key => $value) {
1114
                $html .= $key.'='.$value.'&';
1115
            }
1116
        }
1117
        $html .= 'action=lock&content='.$content.'&id='.$id.'">'.
1118
            Display::return_icon('unlock.png', get_lang('Lock'), [], ICON_SIZE_SMALL).'</a>';
1119
    }
1120
1121
    return $html;
1122
}
1123
1124
/**
1125
 * This function takes care of the display of the up and down icon
1126
 *
1127
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1128
 * @param int $id is the id of the item we want to display the icons for
1129
 * @param $list is an array of all the items. All items in this list should have
1130
 * an up and down icon except for the first (no up icon) and the last (no down icon)
1131
 *          The key of this $list array is the id of the item.
1132
 *
1133
 * @return string HTML
1134
 **/
1135
function return_up_down_icon($content, $id, $list)
1136
{
1137
    $id = (int) $id;
1138
    $total_items = count($list);
1139
    $position = 0;
1140
    $internal_counter = 0;
1141
    $forumCategory = isset($_GET['forumcategory']) ? Security::remove_XSS($_GET['forumcategory']) : null;
1142
1143
    if (is_array($list)) {
1144
        foreach ($list as $key => $listitem) {
1145
            $internal_counter++;
1146
            if ($id == $key) {
1147
                $position = $internal_counter;
1148
            }
1149
        }
1150
    }
1151
1152
    if ($position > 1) {
1153
        $return_value = '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=up&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('MoveUp').'">'.
1154
            Display::return_icon('up.png', get_lang('MoveUp'), [], ICON_SIZE_SMALL).'</a>';
1155
    } else {
1156
        $return_value = Display::return_icon('up_na.png', '-', [], ICON_SIZE_SMALL);
1157
    }
1158
1159
    if ($position < $total_items) {
1160
        $return_value .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&direction=down&content='.$content.'&forumcategory='.$forumCategory.'&id='.$id.'" title="'.get_lang('MoveDown').'" >'.
1161
            Display::return_icon('down.png', get_lang('MoveDown'), [], ICON_SIZE_SMALL).'</a>';
1162
    } else {
1163
        $return_value .= Display::return_icon('down_na.png', '-', [], ICON_SIZE_SMALL);
1164
    }
1165
1166
    return $return_value;
1167
}
1168
1169
/**
1170
 * This function changes the visibility in the database (item_property)
1171
 *
1172
 * @param string $content what is it that we want to make (in)visible: forum category, forum, thread, post
1173
 * @param int $id the id of the content we want to make invisible
1174
 * @param string $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
1175
 *
1176
 * @todo change the get parameter so that it matches the tool constants.
1177
 * @todo check if api_item_property_update returns true or false => returnmessage depends on it.
1178
 * @todo move to itemmanager
1179
 *
1180
 * @return string language variable
1181
 *
1182
 * @author Patrick Cool <[email protected]>, Ghent University
1183
 * @version february 2006, dokeos 1.8
1184
 */
1185
function change_visibility($content, $id, $target_visibility)
1186
{
1187
    $_course = api_get_course_info();
1188
    $constants = [
1189
        'forumcategory' => TOOL_FORUM_CATEGORY,
1190
        'forum' => TOOL_FORUM,
1191
        'thread' => TOOL_FORUM_THREAD,
1192
    ];
1193
    api_item_property_update(
1194
        $_course,
1195
        $constants[$content],
1196
        $id,
1197
        $target_visibility,
1198
        api_get_user_id()
1199
    );
1200
1201
    if ($target_visibility == 'visible') {
1202
        handle_mail_cue($content, $id);
1203
    }
1204
    return get_lang('VisibilityChanged');
1205
}
1206
1207
/**
1208
 * This function changes the lock status in the database
1209
 *
1210
 * @param string $content what is it that we want to (un)lock: forum category, forum, thread, post
1211
 * @param int $id the id of the content we want to (un)lock
1212
 * @param string $action do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
1213
 * @return string language variable
1214
 *
1215
 * @todo move to item manager
1216
 *
1217
 * @author Patrick Cool <[email protected]>, Ghent University
1218
 * @version february 2006, dokeos 1.8
1219
 */
1220
function change_lock_status($content, $id, $action)
1221
{
1222
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1223
    $table_forums = Database::get_course_table(TABLE_FORUM);
1224
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1225
1226
    // Determine the relevant table.
1227
    if ($content == 'forumcategory') {
1228
        $table = $table_categories;
1229
        $id_field = 'cat_id';
1230
    } elseif ($content == 'forum') {
1231
        $table = $table_forums;
1232
        $id_field = 'forum_id';
1233
    } elseif ($content == 'thread') {
1234
        $table = $table_threads;
1235
        $id_field = 'thread_id';
1236
    } else {
1237
        return get_lang('Error');
1238
    }
1239
1240
    // Determine what we are doing => defines the value for the database and the return message.
1241
    if ($action == 'lock') {
1242
        $db_locked = 1;
1243
        $return_message = get_lang('Locked');
1244
    } elseif ($action == 'unlock') {
1245
        $db_locked = 0;
1246
        $return_message = get_lang('Unlocked');
1247
    } else {
1248
        return get_lang('Error');
1249
    }
1250
1251
    $course_id = api_get_course_int_id();
1252
1253
    // Doing the change in the database
1254
    $sql = "UPDATE $table SET locked='".Database::escape_string($db_locked)."'
1255
            WHERE c_id = $course_id AND $id_field='".Database::escape_string($id)."'";
1256
    if (Database::query($sql)) {
1257
        return $return_message;
1258
    } else {
1259
        return get_lang('Error');
1260
    }
1261
}
1262
1263
/**
1264
 * This function moves a forum or a forum category up or down
1265
 *
1266
 * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
1267
 * @param $direction do we want to move it up or down.
1268
 * @param $id the id of the content we want to make invisible
1269
 * @todo consider removing the table_item_property calls here but this can
1270
 * prevent unwanted side effects when a forum does not have an entry in
1271
 * the item_property table but does have one in the forum table.
1272
 * @return string language variable
1273
 *
1274
 * @author Patrick Cool <[email protected]>, Ghent University
1275
 * @version february 2006, dokeos 1.8
1276
 */
1277
function move_up_down($content, $direction, $id)
1278
{
1279
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1280
    $table_forums = Database::get_course_table(TABLE_FORUM);
1281
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1282
    $course_id = api_get_course_int_id();
1283
    $id = intval($id);
1284
1285
    // Determine which field holds the sort order.
1286
    if ($content == 'forumcategory') {
1287
        $table = $table_categories;
1288
        $sort_column = 'cat_order';
1289
        $id_column = 'cat_id';
1290
        $sort_column = 'cat_order';
1291
    } elseif ($content == 'forum') {
1292
        $table = $table_forums;
1293
        $sort_column = 'forum_order';
1294
        $id_column = 'forum_id';
1295
        $sort_column = 'forum_order';
1296
        // We also need the forum_category of this forum.
1297
        $sql = "SELECT forum_category FROM $table_forums
1298
                WHERE c_id = $course_id AND forum_id = ".intval($id);
1299
        $result = Database::query($sql);
1300
        $row = Database::fetch_array($result);
1301
        $forum_category = $row['forum_category'];
1302
    } else {
1303
        return get_lang('Error');
1304
    }
1305
1306
    // Determine the need for sorting ascending or descending order.
1307
    if ($direction == 'down') {
1308
        $sort_direction = 'ASC';
1309
    } elseif ($direction == 'up') {
1310
        $sort_direction = 'DESC';
1311
    } else {
1312
        return get_lang('Error');
1313
    }
1314
1315
    // The SQL statement
1316
    if ($content == 'forumcategory') {
1317
        $sql = "SELECT *
1318
                FROM $table_categories forum_categories, $table_item_property item_properties
1319
                WHERE
1320
                    forum_categories.c_id = $course_id AND
1321
                    item_properties.c_id = $course_id AND
1322
                    forum_categories.cat_id=item_properties.ref AND
1323
                    item_properties.tool='".TOOL_FORUM_CATEGORY."'
1324
                ORDER BY forum_categories.cat_order $sort_direction";
1325
    }
1326
    if ($content == 'forum') {
1327
        $sql = "SELECT *
1328
            FROM $table
1329
            WHERE
1330
                c_id = $course_id AND
1331
                forum_category='".Database::escape_string($forum_category)."'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $forum_category does not seem to be defined for all execution paths leading up to this point.
Loading history...
1332
            ORDER BY forum_order $sort_direction";
1333
    }
1334
    // Finding the items that need to be switched.
1335
    $result = Database::query($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sql does not seem to be defined for all execution paths leading up to this point.
Loading history...
1336
    $found = false;
1337
    while ($row = Database::fetch_array($result)) {
1338
        //echo $row[$id_column].'-';
1339
        if ($found) {
1340
            $next_id = $row[$id_column];
1341
            $next_sort = $row[$sort_column];
1342
            $found = false;
1343
        }
1344
        if ($id == $row[$id_column]) {
1345
            $this_id = $id;
1346
            $this_sort = $row[$sort_column];
1347
            $found = true;
1348
        }
1349
    }
1350
1351
    // Committing the switch.
1352
    // We do an extra check if we do not have illegal values. If your remove this if statement you will
1353
    // be able to mess with the sorting by refreshing the page over and over again.
1354
    if ($this_sort != '' && $next_sort != '' && $next_id != '' && $this_id != '') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $next_sort does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $this_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $next_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $this_sort does not seem to be defined for all execution paths leading up to this point.
Loading history...
1355
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($this_sort)."'
1356
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($next_id)."'";
1357
        Database::query($sql);
1358
1359
        $sql = "UPDATE $table SET $sort_column='".Database::escape_string($next_sort)."'
1360
                WHERE c_id = $course_id AND $id_column='".Database::escape_string($this_id)."'";
1361
        Database::query($sql);
1362
    }
1363
1364
    return get_lang(ucfirst($content).'Moved');
1365
}
1366
1367
/**
1368
 * Retrieve all the information off the forum categories (or one specific) for the current course.
1369
 * The categories are sorted according to their sorting order (cat_order
1370
 *
1371
 * @param int|string $id default ''. When an id is passed we only find the information
1372
 * about that specific forum category. If no id is passed we get all the forum categories.
1373
 * @param int $courseId Optional. The course ID
1374
 * @param int $sessionId Optional. The session ID
1375
 * @return array containing all the information about all the forum categories
1376
 *
1377
 * @author Patrick Cool <[email protected]>, Ghent University
1378
 * @version february 2006, dokeos 1.8
1379
 */
1380
function get_forum_categories($id = '', $courseId = 0, $sessionId = 0)
1381
{
1382
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
1383
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1384
1385
    // Condition for the session
1386
    $session_id = $sessionId ?: api_get_session_id();
1387
    $course_id = $courseId ?: api_get_course_int_id();
1388
1389
    $condition_session = api_get_session_condition(
1390
        $session_id,
1391
        true,
1392
        true,
1393
        'forum_categories.session_id'
1394
    );
1395
    $condition_session .= " AND forum_categories.c_id = $course_id AND item_properties.c_id = $course_id";
1396
1397
    if (empty($id)) {
1398
        $sql = "SELECT *
1399
                FROM $table_item_property item_properties 
1400
                INNER JOIN $table_categories forum_categories
1401
                ON (
1402
                    forum_categories.cat_id = item_properties.ref AND 
1403
                    item_properties.c_id = forum_categories.c_id
1404
                )
1405
                WHERE                    
1406
                    item_properties.visibility = 1 AND
1407
                    item_properties.tool = '".TOOL_FORUM_CATEGORY."'
1408
                    $condition_session
1409
                ORDER BY forum_categories.cat_order ASC";
1410
        if (api_is_allowed_to_edit()) {
1411
            $sql = "SELECT *
1412
                    FROM $table_item_property item_properties  
1413
                    INNER JOIN $table_categories forum_categories
1414
                    ON (
1415
                        forum_categories.cat_id = item_properties.ref AND 
1416
                        item_properties.c_id = forum_categories.c_id
1417
                    )
1418
                    WHERE                        
1419
                        item_properties.visibility<>2 AND
1420
                        item_properties.tool='".TOOL_FORUM_CATEGORY."'
1421
                        $condition_session
1422
                    ORDER BY forum_categories.cat_order ASC";
1423
        }
1424
    } else {
1425
        $sql = "SELECT *
1426
                FROM $table_item_property item_properties 
1427
                INNER JOIN $table_categories forum_categories
1428
                ON (
1429
                    forum_categories.cat_id = item_properties.ref AND 
1430
                    item_properties.c_id = forum_categories.c_id
1431
                )
1432
                WHERE                    
1433
                    item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
1434
                    forum_categories.cat_id = ".intval($id)."
1435
                    $condition_session
1436
                ORDER BY forum_categories.cat_order ASC";
1437
    }
1438
    $result = Database::query($sql);
1439
    $forum_categories_list = [];
1440
    while ($row = Database::fetch_assoc($result)) {
1441
        if (empty($id)) {
1442
            $forum_categories_list[$row['cat_id']] = $row;
1443
        } else {
1444
            $forum_categories_list = $row;
1445
        }
1446
    }
1447
1448
    return $forum_categories_list;
1449
}
1450
1451
/**
1452
 * This function retrieves all the fora in a given forum category
1453
 *
1454
 * @param int $cat_id the id of the forum category
1455
 * @param int $courseId Optional. The course ID
1456
 * @return array containing all the information about the forums (regardless of their category)
1457
 *
1458
 * @author Patrick Cool <[email protected]>, Ghent University
1459
 * @version february 2006, dokeos 1.8
1460
 */
1461
function get_forums_in_category($cat_id, $courseId = 0)
1462
{
1463
    $table_forums = Database::get_course_table(TABLE_FORUM);
1464
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1465
1466
    $forum_list = [];
1467
    $course_id = $courseId ?: api_get_course_int_id();
1468
    $cat_id = (int) $cat_id;
1469
1470
    $sql = "SELECT * FROM $table_forums forum 
1471
            INNER JOIN $table_item_property item_properties
1472
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1473
            WHERE
1474
                forum.forum_category = '".$cat_id."' AND                
1475
                item_properties.visibility = 1 AND
1476
                forum.c_id = $course_id AND
1477
                item_properties.c_id = $course_id AND
1478
                item_properties.tool = '".TOOL_FORUM."'                 
1479
            ORDER BY forum.forum_order ASC";
1480
    if (api_is_allowed_to_edit()) {
1481
        $sql = "SELECT * FROM $table_forums forum  
1482
                INNER JOIN $table_item_property item_properties
1483
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
1484
                WHERE
1485
                    forum.forum_category = '".$cat_id."' AND                    
1486
                    item_properties.visibility <> 2 AND
1487
                    item_properties.tool = '".TOOL_FORUM."' AND
1488
                    item_properties.c_id = $course_id AND
1489
                    forum.c_id = $course_id
1490
                ORDER BY forum_order ASC";
1491
    }
1492
    $result = Database::query($sql);
1493
    while ($row = Database::fetch_array($result)) {
1494
        $forum_list[$row['forum_id']] = $row;
1495
    }
1496
1497
    return $forum_list;
1498
}
1499
1500
/**
1501
 * Retrieve all the forums (regardless of their category) or of only one.
1502
 * The forums are sorted according to the forum_order.
1503
 * Since it does not take the forum category into account there probably
1504
 * will be two or more forums that have forum_order=1, ...
1505
 * @param int $id forum id
1506
 * @param string $course_code
1507
 * @param bool $includeGroupsForum
1508
 * @param int $sessionId
1509
 * @return array an array containing all the information about the forums (regardless of their category)
1510
 * @todo check $sql4 because this one really looks fishy.
1511
 *
1512
 * @author Patrick Cool <[email protected]>, Ghent University
1513
 * @version february 2006, dokeos 1.8
1514
 */
1515
function get_forums(
1516
    $id = '',
1517
    $course_code = '',
1518
    $includeGroupsForum = true,
1519
    $sessionId = 0
1520
) {
1521
    $course_info = api_get_course_info($course_code);
1522
1523
    $table_forums = Database::get_course_table(TABLE_FORUM);
1524
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1525
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1526
1527
    // Condition for the session
1528
    $session_id = intval($sessionId) ?: api_get_session_id();
1529
    $sessionIdLink = $session_id === 0 ? '' : ' AND threads.session_id = item_properties.session_id';
1530
1531
    $condition_session = api_get_session_condition(
1532
        $session_id,
1533
        true,
1534
        false,
1535
        'item_properties.session_id'
1536
    );
1537
1538
    $course_id = $course_info['real_id'];
1539
1540
    $forum_list = [];
1541
    $includeGroupsForumSelect = '';
1542
    if (!$includeGroupsForum) {
1543
        $includeGroupsForumSelect = " AND (forum_of_group = 0 OR forum_of_group IS NULL) ";
1544
    }
1545
1546
    if ($id == '') {
1547
        // Student
1548
        // Select all the forum information of all forums (that are visible to students).
1549
        $sql = "SELECT item_properties.*, forum.* 
1550
                FROM $table_forums forum
1551
                INNER JOIN $table_item_property item_properties
1552
                ON (
1553
                    forum.forum_id = item_properties.ref AND
1554
                    forum.c_id = item_properties.c_id
1555
                )
1556
                WHERE
1557
                    item_properties.visibility = 1 AND
1558
                    item_properties.tool = '".TOOL_FORUM."'
1559
                    $condition_session AND
1560
                    forum.c_id = $course_id AND
1561
                    item_properties.c_id = $course_id
1562
                    $includeGroupsForumSelect
1563
                ORDER BY forum.forum_order ASC";
1564
1565
        // Select the number of threads of the forums (only the threads that are visible).
1566
        $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1567
                FROM $table_threads threads
1568
                INNER JOIN $table_item_property item_properties
1569
                ON (
1570
                    threads.thread_id = item_properties.ref AND
1571
                    threads.c_id = item_properties.c_id
1572
                    $sessionIdLink
1573
                )
1574
                WHERE
1575
                    item_properties.visibility=1 AND
1576
                    item_properties.tool='".TOOL_FORUM_THREAD."' AND
1577
                    threads.c_id = $course_id AND
1578
                    item_properties.c_id = $course_id
1579
                GROUP BY threads.forum_id";
1580
1581
        // Course Admin
1582
        if (api_is_allowed_to_edit()) {
1583
            // Select all the forum information of all forums (that are not deleted).
1584
            $sql = "SELECT item_properties.*, forum.* 
1585
                    FROM $table_forums forum
1586
                    INNER JOIN $table_item_property item_properties
1587
                    ON (
1588
                        forum.forum_id = item_properties.ref AND
1589
                        forum.c_id = item_properties.c_id
1590
                    )
1591
                    WHERE
1592
                        item_properties.visibility <> 2 AND
1593
                        item_properties.tool = '".TOOL_FORUM."'
1594
                        $condition_session AND
1595
                        forum.c_id = $course_id AND
1596
                        item_properties.c_id = $course_id
1597
                        $includeGroupsForumSelect
1598
                    ORDER BY forum_order ASC";
1599
1600
            // Select the number of threads of the forums (only the threads that are not deleted).
1601
            $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id
1602
                    FROM $table_threads threads
1603
                    INNER JOIN $table_item_property item_properties
1604
                    ON (
1605
                        threads.thread_id = item_properties.ref AND
1606
                        threads.c_id = item_properties.c_id
1607
                        $sessionIdLink
1608
                    )
1609
                    WHERE
1610
                        item_properties.visibility<>2 AND
1611
                        item_properties.tool='".TOOL_FORUM_THREAD."' AND
1612
                        threads.c_id = $course_id AND
1613
                        item_properties.c_id = $course_id
1614
                    GROUP BY threads.forum_id";
1615
        }
1616
    } else {
1617
        // GETTING ONE SPECIFIC FORUM
1618
        /* We could do the splitup into student and course admin also but we want
1619
        to have as much as information about a certain forum as possible
1620
        so we do not take too much information into account. This function
1621
         (or this section of the function) is namely used to fill the forms
1622
        when editing a forum (and for the moment it is the only place where
1623
        we use this part of the function) */
1624
1625
        // Select all the forum information of the given forum (that is not deleted).
1626
        $sql = "SELECT * FROM $table_item_property item_properties 
1627
                INNER JOIN $table_forums forum
1628
                ON (forum.forum_id = item_properties.ref AND forum.c_id = item_properties.c_id)
1629
                WHERE
1630
                    forum.forum_id = ".intval($id)." AND
1631
                    forum.c_id = $course_id AND
1632
                    item_properties.visibility != 2 AND
1633
                    item_properties.tool = '".TOOL_FORUM."'
1634
                ORDER BY forum_order ASC";
1635
1636
        // Select the number of threads of the forum.
1637
        $sql2 = "SELECT count(*) AS number_of_threads, forum_id
1638
                FROM $table_threads
1639
                WHERE
1640
                    forum_id = ".intval($id)."
1641
                GROUP BY forum_id";
1642
    }
1643
1644
    // Handling all the forum information.
1645
    $result = Database::query($sql);
1646
    while ($row = Database::fetch_assoc($result)) {
1647
        if ($id == '') {
1648
            $forum_list[$row['forum_id']] = $row;
1649
        } else {
1650
            $forum_list = $row;
1651
        }
1652
    }
1653
1654
    // Handling the thread count information.
1655
    $result2 = Database::query($sql2);
1656
    while ($row2 = Database::fetch_array($result2)) {
1657
        if ($id == '') {
1658
            $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
1659
        } else {
1660
            $forum_list['number_of_threads'] = $row2['number_of_threads'];
1661
        }
1662
    }
1663
1664
    /* Finding the last post information
1665
    (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)*/
1666
    if ($id == '') {
1667
        if (is_array($forum_list)) {
1668
            foreach ($forum_list as $key => $value) {
1669
                $last_post_info_of_forum = get_last_post_information(
1670
                    $key,
1671
                    api_is_allowed_to_edit(),
1672
                    $course_id
1673
                );
1674
1675
                if ($last_post_info_of_forum) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $last_post_info_of_forum of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1676
                    $forum_list[$key]['last_post_id'] = $last_post_info_of_forum['last_post_id'];
1677
                    $forum_list[$key]['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
1678
                    $forum_list[$key]['last_post_date'] = $last_post_info_of_forum['last_post_date'];
1679
                    $forum_list[$key]['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
1680
                    $forum_list[$key]['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
1681
                    $forum_list[$key]['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
1682
                }
1683
            }
1684
        } else {
1685
            $forum_list = [];
1686
        }
1687
    } else {
1688
        $last_post_info_of_forum = get_last_post_information(
1689
            $id,
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type string; however, parameter $forum_id of get_last_post_information() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1689
            /** @scrutinizer ignore-type */ $id,
Loading history...
1690
            api_is_allowed_to_edit(),
1691
            $course_id
1692
        );
1693
        if ($last_post_info_of_forum) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $last_post_info_of_forum of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1694
            $forum_list['last_post_id'] = $last_post_info_of_forum['last_post_id'];
1695
            $forum_list['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
1696
            $forum_list['last_post_date'] = $last_post_info_of_forum['last_post_date'];
1697
            $forum_list['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
1698
            $forum_list['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
1699
            $forum_list['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
1700
        }
1701
    }
1702
1703
    return $forum_list;
1704
}
1705
1706
/**
1707
 * @param int $course_id
1708
 * @param int $thread_id
1709
 * @param int $forum_id
1710
 * @param bool $show_visible
1711
 * @return array|bool
1712
 */
1713
function get_last_post_by_thread($course_id, $thread_id, $forum_id, $show_visible = true)
1714
{
1715
    if (empty($thread_id) || empty($forum_id) || empty($course_id)) {
1716
        return false;
1717
    }
1718
1719
    $thread_id = intval($thread_id);
1720
    $forum_id = intval($forum_id);
1721
    $course_id = intval($course_id);
1722
1723
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1724
    $sql = "SELECT * FROM $table_posts
1725
            WHERE 
1726
                c_id = $course_id AND 
1727
                thread_id = $thread_id AND 
1728
                forum_id = $forum_id";
1729
1730
    if ($show_visible == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1731
        $sql .= " AND visible = 1 ";
1732
    }
1733
1734
    $sql .= " ORDER BY post_id DESC LIMIT 1";
1735
    $result = Database::query($sql);
1736
    if (Database::num_rows($result)) {
1737
        return Database::fetch_array($result, 'ASSOC');
1738
    } else {
1739
        return false;
1740
    }
1741
}
1742
1743
/**
1744
 * This function gets all the last post information of a certain forum
1745
 *
1746
 * @param int $forum_id the id of the forum we want to know the last post information of.
1747
 * @param bool $show_invisibles
1748
 * @param string course db name
1749
 * @param int $sessionId Optional. The session id
1750
 * @return array containing all the information about the last post
1751
 * (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
1752
 * @author Patrick Cool <[email protected]>, Ghent University
1753
 * @version february 2006, dokeos 1.8
1754
 */
1755
function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null, $sessionId = 0)
1756
{
1757
    if (!isset($course_id)) {
1758
        $course_id = api_get_course_int_id();
1759
    } else {
1760
        $course_id = intval($course_id);
1761
    }
1762
    $sessionId = $sessionId ? intval($sessionId) : api_get_session_id();
1763
1764
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
1765
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1766
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1767
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1768
1769
    $forum_id = intval($forum_id);
1770
    $return_array = [];
1771
1772
    // First get the threads to make sure there is no inconsistency in the
1773
    // database between forum and thread
1774
    $sql = "SELECT thread_id FROM $table_threads 
1775
            WHERE 
1776
                forum_id = $forum_id AND 
1777
                c_id = $course_id AND 
1778
                session_id = $sessionId";
1779
    $result = Database::query($sql);
1780
    if (Database::num_rows($result) == 0) {
1781
        // If there are no threads in this forum, then there are no posts
1782
        return [];
1783
    }
1784
    $threads = [];
1785
    while ($row = Database::fetch_row($result)) {
1786
        $threads[] = $row[0];
1787
    }
1788
    $threadsList = implode(',', $threads);
1789
    // Now get the posts that are linked to these threads
1790
    $sql = "SELECT
1791
                post.post_id,
1792
                post.forum_id,
1793
                post.poster_id,
1794
                post.poster_name,
1795
                post.post_date,
1796
                users.lastname,
1797
                users.firstname,
1798
                post.visible,
1799
                thread_properties.visibility AS thread_visibility,
1800
                forum_properties.visibility AS forum_visibility
1801
            FROM
1802
                $table_posts post,
1803
                $table_users users,
1804
                $table_item_property thread_properties,
1805
                $table_item_property forum_properties
1806
            WHERE
1807
                post.forum_id = $forum_id
1808
                AND post.thread_id IN ($threadsList)
1809
                AND post.poster_id = users.user_id
1810
                AND post.thread_id = thread_properties.ref
1811
                AND thread_properties.tool='".TOOL_FORUM_THREAD."'
1812
                AND post.forum_id=forum_properties.ref
1813
                AND forum_properties.tool='".TOOL_FORUM."'
1814
                AND post.c_id = $course_id AND
1815
                thread_properties.c_id = $course_id AND
1816
                forum_properties.c_id = $course_id
1817
            ORDER BY post.post_id DESC";
1818
    $result = Database::query($sql);
1819
1820
    if ($show_invisibles) {
1821
        $row = Database::fetch_array($result);
1822
        $return_array['last_post_id'] = $row['post_id'];
1823
        $return_array['last_poster_id'] = $row['poster_id'];
1824
        $return_array['last_post_date'] = $row['post_date'];
1825
        $return_array['last_poster_name'] = $row['poster_name'];
1826
        $return_array['last_poster_lastname'] = $row['lastname'];
1827
        $return_array['last_poster_firstname'] = $row['firstname'];
1828
1829
        return $return_array;
1830
    } else {
1831
        // We have to loop through the results to find the first one that is
1832
        // actually visible to students (forum_category, forum, thread AND post are visible).
1833
        while ($row = Database::fetch_array($result)) {
1834
            if ($row['visible'] == '1' && $row['thread_visibility'] == '1' && $row['forum_visibility'] == '1') {
1835
                $return_array['last_post_id'] = $row['post_id'];
1836
                $return_array['last_poster_id'] = $row['poster_id'];
1837
                $return_array['last_post_date'] = $row['post_date'];
1838
                $return_array['last_poster_name'] = $row['poster_name'];
1839
                $return_array['last_poster_lastname'] = $row['lastname'];
1840
                $return_array['last_poster_firstname'] = $row['firstname'];
1841
1842
                return $return_array;
1843
            }
1844
        }
1845
    }
1846
}
1847
1848
/**
1849
 * Retrieve all the threads of a given forum
1850
 *
1851
 * @param int $forum_id
1852
 * @param int|null $courseId Optional If is null then it is considered the current course
1853
 * @param int|null $sessionId Optional. If is null then it is considered the current session
1854
 * @return array containing all the information about the threads
1855
 *
1856
 * @author Patrick Cool <[email protected]>, Ghent University
1857
 * @version february 2006, dokeos 1.8
1858
 */
1859
function get_threads($forum_id, $courseId = null, $sessionId = null)
1860
{
1861
    $groupId = api_get_group_id();
1862
    $sessionId = $sessionId !== null ? intval($sessionId) : api_get_session_id();
1863
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
1864
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
1865
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
1866
1867
    $courseId = $courseId !== null ? intval($courseId) : api_get_course_int_id();
1868
    $groupInfo = GroupManager::get_group_properties($groupId);
1869
    $groupCondition = '';
1870
1871
    if (!empty($groupInfo)) {
1872
        $groupIid = $groupInfo['iid'];
1873
        $groupCondition = " AND item_properties.to_group_id = '$groupIid' ";
1874
    }
1875
1876
    $sessionCondition = api_get_session_condition(
1877
        $sessionId,
1878
        true,
1879
        false,
1880
        'item_properties.session_id'
1881
    );
1882
1883
    // important note:  it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
1884
    // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
1885
    // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
1886
    // This is why it is added to the end of the field selection
1887
    $sql = "SELECT DISTINCT
1888
                item_properties.*,
1889
                users.firstname,
1890
                users.lastname,
1891
                users.user_id,
1892
                thread.locked as locked,
1893
                thread.*
1894
            FROM $table_threads thread
1895
            INNER JOIN $table_item_property item_properties
1896
            ON
1897
                thread.thread_id = item_properties.ref AND
1898
                item_properties.c_id = thread.c_id AND
1899
                item_properties.tool = '".TABLE_FORUM_THREAD."' 
1900
                $groupCondition
1901
                $sessionCondition
1902
            LEFT JOIN $table_users users
1903
                ON thread.thread_poster_id = users.user_id
1904
            WHERE
1905
                item_properties.visibility='1' AND
1906
                thread.forum_id = ".intval($forum_id)." AND
1907
                thread.c_id = $courseId 
1908
            ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
1909
1910
    if (api_is_allowed_to_edit()) {
1911
        $sql = "SELECT DISTINCT
1912
                    item_properties.*,
1913
                    users.firstname,
1914
                    users.lastname,
1915
                    users.user_id,
1916
                    thread.locked as locked,
1917
                    thread.*
1918
                FROM $table_threads thread
1919
                INNER JOIN $table_item_property item_properties
1920
                ON
1921
                    thread.thread_id = item_properties.ref AND
1922
                    item_properties.c_id = thread.c_id AND
1923
                    item_properties.tool = '".TABLE_FORUM_THREAD."'
1924
                    $groupCondition
1925
                    $sessionCondition
1926
                LEFT JOIN $table_users users
1927
                    ON thread.thread_poster_id=users.user_id
1928
                WHERE
1929
                    item_properties.visibility<>2 AND
1930
                    thread.forum_id = ".intval($forum_id)." AND
1931
                    thread.c_id = $courseId 
1932
                ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
1933
    }
1934
    $result = Database::query($sql);
1935
    $list = [];
1936
    $alreadyAdded = [];
1937
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1938
        if (in_array($row['thread_id'], $alreadyAdded)) {
1939
            continue;
1940
        }
1941
        $list[] = $row;
1942
        $alreadyAdded[] = $row['thread_id'];
1943
    }
1944
1945
    return $list;
1946
}
1947
1948
/**
1949
 * Get a thread by Id and course id
1950
 *
1951
 * @param int $threadId the thread Id
1952
 * @param int $cId the course id
1953
 * @return array containing all the information about the thread
1954
 */
1955
function getThreadInfo($threadId, $cId)
1956
{
1957
    $repo = Database::getManager()->getRepository('ChamiloCourseBundle:CForumThread');
1958
    $forumThread = $repo->findOneBy(['threadId' => $threadId, 'cId' => $cId]);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $forumThread is correct as $repo->findOneBy(array('...readId, 'cId' => $cId)) targeting Doctrine\ORM\EntityRepository::findOneBy() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1959
1960
    $thread = [];
1961
    if ($forumThread) {
1962
        $thread['threadId'] = $forumThread->getThreadId();
1963
        $thread['threadTitle'] = $forumThread->getThreadTitle();
1964
        $thread['forumId'] = $forumThread->getForumId();
1965
        $thread['sessionId'] = $forumThread->getSessionId();
1966
        $thread['threadSticky'] = $forumThread->getThreadSticky();
1967
        $thread['locked'] = $forumThread->getLocked();
1968
        $thread['threadTitleQualify'] = $forumThread->getThreadTitleQualify();
1969
        $thread['threadQualifyMax'] = $forumThread->getThreadQualifyMax();
1970
        $thread['threadCloseDate'] = $forumThread->getThreadCloseDate();
1971
        $thread['threadWeight'] = $forumThread->getThreadWeight();
1972
        $thread['threadPeerQualify'] = $forumThread->isThreadPeerQualify();
1973
    }
1974
1975
    return $thread;
1976
}
1977
1978
/**
1979
 * Retrieve all posts of a given thread
1980
 * @param array $forumInfo
1981
 * @param int $threadId The thread ID
1982
 * @param string $orderDirection Optional. The direction for sort the posts
1983
 * @param boolean $recursive Optional. If the list is recursive
1984
 * @param int $postId Optional. The post ID for recursive list
1985
 * @param int $depth Optional. The depth to indicate the indent
1986
 * @todo move to a repository
1987
 *
1988
 * @return array containing all the information about the posts of a given thread
1989
 */
1990
function getPosts(
1991
    $forumInfo,
1992
    $threadId,
1993
    $orderDirection = 'ASC',
1994
    $recursive = false,
1995
    $postId = null,
1996
    $depth = -1
1997
) {
1998
    $em = Database::getManager();
1999
2000
    if (api_is_allowed_to_edit(false, true)) {
2001
        $visibleCriteria = Criteria::expr()->neq('visible', 2);
2002
    } else {
2003
        $visibleCriteria = Criteria::expr()->eq('visible', 1);
2004
    }
2005
2006
    $criteria = Criteria::create();
2007
    $criteria
2008
        ->where(Criteria::expr()->eq('threadId', $threadId))
2009
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
2010
        ->andWhere($visibleCriteria)
2011
    ;
2012
2013
    $groupId = api_get_group_id();
2014
    $groupInfo = GroupManager::get_group_properties($groupId);
2015
    $filterModerated = true;
2016
2017
    if (empty($groupId)) {
2018
        if (api_is_allowed_to_edit()) {
2019
            $filterModerated = false;
2020
        }
2021
    } else {
2022
        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo) ||
2023
            api_is_allowed_to_edit(false, true)
2024
        ) {
2025
            $filterModerated = false;
2026
        }
2027
    }
2028
2029
    if ($recursive) {
2030
        $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
2031
    }
2032
2033
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
2034
    $qb->select('p')
2035
        ->addCriteria($criteria)
2036
        ->addOrderBy('p.postId', $orderDirection);
2037
2038
    if ($filterModerated && $forumInfo['moderated'] == 1) {
2039
        if (!api_is_allowed_to_edit(false, true)) {
2040
            $userId = api_get_user_id();
2041
            $qb->andWhere(
2042
                "p.status = 1 OR 
2043
                    (p.status = ".CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
2044
                    (p.status = ".CForumPost::STATUS_REJECTED." AND p.posterId = $userId) OR
2045
                    (p.status IS NULL AND p.posterId = $userId) 
2046
                    "
2047
            );
2048
        }
2049
    }
2050
2051
    $posts = $qb->getQuery()->getResult();
2052
    $depth++;
2053
2054
    $list = [];
2055
    /** @var CForumPost $post */
2056
    foreach ($posts as $post) {
2057
        $postInfo = [
2058
            'iid' => $post->getIid(),
2059
            'c_id' => $post->getCId(),
2060
            'post_id' => $post->getPostId(),
2061
            'post_title' => $post->getPostTitle(),
2062
            'post_text' => $post->getPostText(),
2063
            'thread_id' => $post->getThreadId(),
2064
            'forum_id' => $post->getForumId(),
2065
            'poster_id' => $post->getPosterId(),
2066
            'poster_name' => $post->getPosterName(),
2067
            'post_date' => $post->getPostDate(),
2068
            'post_notification' => $post->getPostNotification(),
2069
            'post_parent_id' => $post->getPostParentId(),
2070
            'visible' => $post->getVisible(),
2071
            'status' => $post->getStatus(),
2072
            'indent_cnt' => $depth
2073
        ];
2074
2075
        $posterId = $post->getPosterId();
2076
        if (!empty($posterId)) {
2077
            $user = api_get_user_entity($posterId);
2078
            if ($user) {
2079
                $postInfo['user_id'] = $user->getUserId();
2080
                $postInfo['username'] = $user->getUsername();
2081
                $postInfo['username_canonical'] = $user->getUsernameCanonical();
2082
                $postInfo['lastname'] = $user->getLastname();
2083
                $postInfo['firstname'] = $user->getFirstname();
2084
                $postInfo['complete_name'] = $user->getCompleteName();
2085
            }
2086
        }
2087
2088
        $list[] = $postInfo;
2089
2090
        if (!$recursive) {
2091
            continue;
2092
        }
2093
        $list = array_merge(
2094
            $list,
2095
            getPosts(
2096
                $forumInfo,
2097
                $threadId,
2098
                $orderDirection,
2099
                $recursive,
2100
                $post->getPostId(),
2101
                $depth
2102
            )
2103
        );
2104
    }
2105
2106
    return $list;
2107
}
2108
2109
/**
2110
 * This function retrieves all the information of a post
2111
 *
2112
 * @param int $post_id integer that indicates the forum
2113
 *
2114
 * @return array returns
2115
 *
2116
 * @author Patrick Cool <[email protected]>, Ghent University
2117
 * @version february 2006, dokeos 1.8
2118
 */
2119
function get_post_information($post_id)
2120
{
2121
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
2122
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
2123
    $course_id = api_get_course_int_id();
2124
2125
    $sql = "SELECT posts.*, email FROM ".$table_posts." posts, ".$table_users." users
2126
            WHERE
2127
                c_id = $course_id AND
2128
                posts.poster_id=users.user_id AND
2129
                posts.post_id = ".intval($post_id);
2130
    $result = Database::query($sql);
2131
    $row = Database::fetch_array($result, 'ASSOC');
2132
2133
    return $row;
2134
}
2135
2136
/**
2137
 * This function retrieves all the information of a thread
2138
 *
2139
 * @param int $forumId
2140
 * @param $thread_id integer that indicates the forum
2141
 * @param int|null $sessionId Optional. If is null then it is considered the current session
2142
 * @return array returns
2143
 *
2144
 * @author Patrick Cool <[email protected]>, Ghent University
2145
 * @version february 2006, dokeos 1.8
2146
 */
2147
function get_thread_information($forumId, $thread_id, $sessionId = null)
2148
{
2149
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2150
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2151
    $thread_id = intval($thread_id);
2152
    $sessionId = $sessionId !== null ? intval($sessionId) : api_get_session_id();
2153
    $sessionCondition = api_get_session_condition(
2154
        $sessionId,
2155
        true,
2156
        false,
2157
        'threads.session_id'
2158
    );
2159
    $forumCondition = '';
2160
    if (!empty($forumId)) {
2161
        $forumId = (int) $forumId;
2162
        $forumCondition = " threads.forum_id = $forumId AND ";
2163
    }
2164
    $sql = "SELECT * FROM $table_item_property item_properties
2165
            INNER JOIN
2166
            $table_threads threads
2167
            ON (item_properties.ref = threads.thread_id AND threads.c_id = item_properties.c_id)
2168
            WHERE
2169
                $forumCondition
2170
                item_properties.tool= '".TOOL_FORUM_THREAD."' AND                
2171
                threads.thread_id = $thread_id 
2172
                $sessionCondition
2173
            ";
2174
2175
    $result = Database::query($sql);
2176
    $row = Database::fetch_assoc($result);
2177
2178
    return $row;
2179
}
2180
2181
/**
2182
 * This function retrieves forum thread users details
2183
 * @param   int Thread ID
2184
 * @param   string  Course DB name (optional)
2185
 * @return  Doctrine\DBAL\Driver\Statement|null array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2186
 * @author Christian Fasanando <[email protected]>,
2187
 * @todo     this function need to be improved
2188
 * @version octubre 2008, dokeos 1.8
2189
 */
2190
function get_thread_users_details($thread_id)
2191
{
2192
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2193
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2194
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2195
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2196
2197
    $course_id = api_get_course_int_id();
2198
2199
    $is_western_name_order = api_is_western_name_order();
2200
    if ($is_western_name_order) {
2201
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2202
    } else {
2203
        $orderby = 'ORDER BY user.lastname, user.firstname';
2204
    }
2205
2206
    if (api_get_session_id()) {
2207
        $session_info = api_get_session_info(api_get_session_id());
2208
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2209
        //not showing coaches
2210
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2211
                FROM $t_posts p, $t_users user, $t_session_rel_user session_rel_user_rel_course
2212
                WHERE 
2213
                    p.poster_id = user.id AND
2214
                    user.id = session_rel_user_rel_course.user_id AND
2215
                    session_rel_user_rel_course.status<>'2' AND
2216
                    session_rel_user_rel_course.user_id NOT IN ($user_to_avoid) AND
2217
                    p.thread_id = ".intval($thread_id)." AND
2218
                    session_id = ".api_get_session_id()." AND
2219
                    p.c_id = $course_id AND
2220
                    session_rel_user_rel_course.c_id = ".$course_id." $orderby ";
2221
    } else {
2222
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, thread_id
2223
                FROM $t_posts p, $t_users user, $t_course_user course_user
2224
                WHERE 
2225
                    p.poster_id = user.id
2226
                    AND user.id = course_user.user_id
2227
                    AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2228
                    AND p.thread_id = ".intval($thread_id)."
2229
                    AND course_user.status NOT IN('1') AND
2230
                    p.c_id = $course_id AND
2231
                    course_user.c_id = ".$course_id." $orderby";
2232
    }
2233
    $result = Database::query($sql);
2234
2235
    return $result;
2236
}
2237
2238
/**
2239
 * This function retrieves forum thread users qualify
2240
 * @param   int Thread ID
2241
 * @param   string  Course DB name (optional)
2242
 * @return  Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2243
 * @author Jhon Hinojosa
2244
 * @todo     this function need to be improved
2245
 */
2246
function get_thread_users_qualify($thread_id)
2247
{
2248
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2249
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2250
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2251
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2252
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2253
2254
    $course_id = api_get_course_int_id();
2255
    $sessionId = api_get_session_id();
2256
2257
    $is_western_name_order = api_is_western_name_order();
2258
    if ($is_western_name_order) {
2259
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2260
    } else {
2261
        $orderby = 'ORDER BY user.lastname, user.firstname';
2262
    }
2263
2264
    if ($sessionId) {
2265
        $session_info = api_get_session_info($sessionId);
2266
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2267
        //not showing coaches
2268
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2269
                FROM $t_posts post , $t_users user, $t_session_rel_user scu, $t_qualify qualify
2270
                WHERE poster_id = user.id
2271
                    AND post.poster_id = qualify.user_id
2272
                    AND user.id = scu.user_id
2273
                    AND scu.status<>'2'
2274
                    AND scu.user_id NOT IN ($user_to_avoid)
2275
                    AND qualify.thread_id = ".intval($thread_id)."
2276
                    AND post.thread_id = ".intval($thread_id)."
2277
                    AND scu.session_id = $sessionId
2278
                    AND scu.c_id = ".$course_id." AND
2279
                    qualify.c_id = $course_id AND
2280
                    post.c_id = $course_id
2281
                $orderby ";
2282
    } else {
2283
        $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.id,qualify.qualify
2284
                FROM $t_posts post,
2285
                     $t_qualify qualify,
2286
                     $t_users user,
2287
                     $t_course_user course_user
2288
                WHERE
2289
                     post.poster_id = user.id
2290
                     AND post.poster_id = qualify.user_id
2291
                     AND user.id = course_user.user_id
2292
                     AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2293
                     AND qualify.thread_id = ".intval($thread_id)."
2294
                     AND post.thread_id = ".intval($thread_id)."
2295
                     AND course_user.status not in('1')
2296
                     AND course_user.c_id = $course_id
2297
                     AND qualify.c_id = $course_id
2298
                     AND post.c_id = $course_id
2299
                 $orderby ";
2300
    }
2301
    $result = Database::query($sql);
2302
2303
    return $result;
2304
}
2305
2306
/**
2307
 * This function retrieves forum thread users not qualify
2308
 * @param   int Thread ID
2309
 * @param   string  Course DB name (optional)
2310
 * @return  Doctrine\DBAL\Driver\Statement|null Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
2311
 * @author   Jhon Hinojosa<[email protected]>,
2312
 * @version oct 2008, dokeos 1.8
2313
 */
2314
function get_thread_users_not_qualify($thread_id)
2315
{
2316
    $t_posts = Database::get_course_table(TABLE_FORUM_POST);
2317
    $t_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
2318
    $t_users = Database::get_main_table(TABLE_MAIN_USER);
2319
    $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2320
    $t_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2321
2322
    $is_western_name_order = api_is_western_name_order();
2323
    if ($is_western_name_order) {
2324
        $orderby = 'ORDER BY user.firstname, user.lastname ';
2325
    } else {
2326
        $orderby = 'ORDER BY user.lastname, user.firstname';
2327
    }
2328
2329
    $course_id = api_get_course_int_id();
2330
2331
    $sql1 = "SELECT user_id FROM  $t_qualify
2332
             WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
2333
    $result1 = Database::query($sql1);
2334
    $cad = '';
2335
    while ($row = Database::fetch_array($result1)) {
2336
        $cad .= $row['user_id'].',';
2337
    }
2338
    if ($cad == '') {
2339
        $cad = '0';
2340
    } else {
2341
        $cad = substr($cad, 0, strlen($cad) - 1);
2342
    }
2343
2344
    if (api_get_session_id()) {
2345
        $session_info = api_get_session_info(api_get_session_id());
2346
        $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
2347
        //not showing coaches
2348
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2349
                FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
2350
                WHERE poster_id = user.id
2351
                    AND user.id NOT IN (".$cad.")
2352
                    AND user.id = session_rel_user_rel_course.user_id
2353
                    AND session_rel_user_rel_course.status<>'2'
2354
                    AND session_rel_user_rel_course.user_id NOT IN ($user_to_avoid)
2355
                    AND post.thread_id = ".intval($thread_id)."
2356
                    AND session_id = ".api_get_session_id()."
2357
                    AND session_rel_user_rel_course.c_id = $course_id AND post.c_id = $course_id $orderby ";
2358
    } else {
2359
        $sql = "SELECT DISTINCT user.id, user.lastname, user.firstname, post.thread_id
2360
                FROM $t_posts post, $t_users user,$t_course_user course_user
2361
                WHERE post.poster_id = user.id
2362
                AND user.id NOT IN (".$cad.")
2363
                AND user.id = course_user.user_id
2364
                AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
2365
                AND post.thread_id = ".intval($thread_id)."
2366
                AND course_user.status not in('1')
2367
                AND course_user.c_id = $course_id AND post.c_id = $course_id  $orderby";
2368
    }
2369
    $result = Database::query($sql);
2370
2371
    return $result;
2372
}
2373
2374
/**
2375
 * This function retrieves all the information of a given forum_id
2376
 *
2377
 * @param $forum_id integer that indicates the forum
2378
 * @return array returns
2379
 *
2380
 * @author Patrick Cool <[email protected]>, Ghent University
2381
 * @version february 2006, dokeos 1.8
2382
 *
2383
 * @deprecated this functionality is now moved to get_forums($forum_id)
2384
 */
2385
function get_forum_information($forum_id, $courseId = 0)
2386
{
2387
    $table_forums = Database::get_course_table(TABLE_FORUM);
2388
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2389
    $courseId = empty($courseId) ? api_get_course_int_id() : intval($courseId);
2390
    $forum_id = intval($forum_id);
2391
2392
    $sql = "SELECT *
2393
            FROM $table_forums forums
2394
            INNER JOIN $table_item_property item_properties
2395
            ON (forums.c_id = item_properties.c_id)
2396
            WHERE
2397
                item_properties.tool = '".TOOL_FORUM."' AND
2398
                item_properties.ref = '".$forum_id."' AND
2399
                forums.forum_id = '".$forum_id."' AND
2400
                forums.c_id = ".$courseId."
2401
            ";
2402
2403
    $result = Database::query($sql);
2404
    $row = Database::fetch_array($result, 'ASSOC');
2405
    $row['approval_direct_post'] = 0;
2406
    // We can't anymore change this option, so it should always be activated.
2407
2408
    return $row;
2409
}
2410
2411
/**
2412
 * This function retrieves all the information of a given forumcategory id
2413
 *
2414
 * @param $cat_id integer that indicates the forum
2415
 *
2416
 * @return array returns if there are category or bool returns if there aren't category
2417
 * @author Patrick Cool <[email protected]>, Ghent University
2418
 * @version february 2006, dokeos 1.8
2419
 */
2420
function get_forumcategory_information($cat_id)
2421
{
2422
    $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
2423
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
2424
2425
    $course_id = api_get_course_int_id();
2426
    $sql = "SELECT *
2427
            FROM $table_categories forumcategories 
2428
            INNER JOIN $table_item_property item_properties
2429
            ON (forumcategories.c_id = item_properties.c_id)
2430
            WHERE
2431
                forumcategories.c_id = $course_id AND
2432
                item_properties.c_id = $course_id AND
2433
                item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
2434
                item_properties.ref='".Database::escape_string($cat_id)."' AND
2435
                forumcategories.cat_id='".Database::escape_string($cat_id)."'";
2436
    $result = Database::query($sql);
2437
    $row = Database::fetch_array($result);
2438
2439
    return $row;
2440
}
2441
2442
/**
2443
 * This function counts the number of forums inside a given category
2444
 *
2445
 * @param int $cat_id the id of the forum category
2446
 * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
2447
 *      of visible forums, $countinvisible=1 would return the number of visible and invisible forums
2448
 * @return int the number of forums inside the given category
2449
 *
2450
 * @author Patrick Cool <[email protected]>, Ghent University
2451
 * @version february 2006, dokeos 1.8
2452
 */
2453
function count_number_of_forums_in_category($cat_id)
2454
{
2455
    $table_forums = Database::get_course_table(TABLE_FORUM);
2456
    $course_id = api_get_course_int_id();
2457
    $sql = "SELECT count(*) AS number_of_forums
2458
            FROM ".$table_forums."
2459
            WHERE c_id = $course_id AND forum_category='".Database::escape_string($cat_id)."'";
2460
    $result = Database::query($sql);
2461
    $row = Database::fetch_array($result);
2462
2463
    return $row['number_of_forums'];
2464
}
2465
2466
/**
2467
 * This function update a thread
2468
 *
2469
 * @param array $values - The form Values
2470
 * @return void HTML
2471
 *
2472
 */
2473
function updateThread($values)
2474
{
2475
    if (!api_is_allowed_to_edit()) {
2476
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type void.
Loading history...
2477
    }
2478
2479
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
2480
    $courseId = api_get_course_int_id();
2481
    $courseCode = api_get_course_id();
2482
    $sessionId = api_get_session_id();
2483
2484
    // Simple update + set gradebook values to null
2485
    $params = [
2486
        'thread_title' => $values['thread_title'],
2487
        'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0
2488
    ];
2489
    $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2490
    Database::update($threadTable, $params, $where);
2491
2492
    $id = $values['thread_id'];
2493
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
2494
        $courseCode,
2495
        LINK_FORUM_THREAD,
2496
        $id,
2497
        $sessionId
2498
    );
2499
    $linkId = $linkInfo['id'];
2500
    $em = Database::getManager();
2501
    $gradebookLink = null;
2502
    if (!empty($linkId)) {
2503
        $gradebookLink = $em->getRepository('ChamiloCoreBundle:GradebookLink')->find($linkId);
2504
    }
2505
2506
    // values 1 or 0
2507
    $check = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : false;
2508
    if ($check) {
2509
        $title = Security::remove_XSS(stripslashes($values['calification_notebook_title']));
2510
        $value = isset($values['numeric_calification']) ? intval($values['numeric_calification']) : 0;
2511
        $weight = isset($values['weight_calification']) ? floatval($values['weight_calification']) : 0;
2512
        $description = '';
2513
        // Update title
2514
        $params = [
2515
            'thread_title_qualify' => $values['calification_notebook_title'],
2516
            'thread_qualify_max' => api_float_val($values['numeric_calification']),
2517
            'thread_weight' => api_float_val($values['weight_calification']),
2518
            'thread_peer_qualify' => $values['thread_peer_qualify'],
2519
        ];
2520
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2521
        Database::update($threadTable, $params, $where);
2522
2523
        if (!$linkInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $linkInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2524
            GradebookUtils::add_resource_to_course_gradebook(
2525
                $values['category_id'],
2526
                $courseCode,
2527
                LINK_FORUM_THREAD,
2528
                $id,
2529
                $title,
2530
                $weight,
2531
                $value,
2532
                $description,
2533
                1,
2534
                $sessionId
2535
            );
2536
        } else {
2537
            if ($gradebookLink) {
2538
                $gradebookLink->setWeight($weight);
2539
                $em->persist($gradebookLink);
2540
                $em->flush();
2541
            }
2542
        }
2543
    } else {
2544
        $params = [
2545
            'thread_title_qualify' => '',
2546
            'thread_qualify_max' => '',
2547
            'thread_weight' => '',
2548
            'thread_peer_qualify' => '',
2549
        ];
2550
        $where = ['c_id = ? AND thread_id = ?' => [$courseId, $values['thread_id']]];
2551
        Database::update($threadTable, $params, $where);
2552
2553
        if (!empty($linkInfo)) {
2554
            if ($gradebookLink) {
2555
                $em->remove($gradebookLink);
2556
                $em->flush();
2557
            }
2558
        }
2559
    }
2560
2561
    $message = get_lang('EditPostStored').'<br />';
2562
    Display::addFlash(Display::return_message($message, 'confirmation', false));
2563
}
2564
2565
/**
2566
 * This function stores a new thread. This is done through an entry in the forum_thread table AND
2567
 * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet))
2568
 *
2569
 * @param array $current_forum
2570
 * @param array $values
2571
 * @param array $courseInfo
2572
 * @param bool $showMessage
2573
 * @param int $userId Optional. The user ID
2574
 * @param int $sessionId
2575
 * @return int
2576
 * @author Patrick Cool <[email protected]>, Ghent University
2577
 * @version february 2006, dokeos 1.8
2578
 */
2579
function store_thread(
2580
    $current_forum,
2581
    $values,
2582
    $courseInfo = [],
2583
    $showMessage = true,
2584
    $userId = 0,
2585
    $sessionId = 0
2586
) {
2587
    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
2588
    $userId = $userId ?: api_get_user_id();
2589
    $course_id = $courseInfo['real_id'];
2590
    $courseCode = $courseInfo['code'];
2591
    $groupId = api_get_group_id();
2592
    $groupInfo = GroupManager::get_group_properties($groupId);
2593
    $sessionId = $sessionId ?: api_get_session_id();
2594
2595
    $em = Database::getManager();
2596
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
2597
    $upload_ok = 1;
2598
    $has_attachment = false;
2599
2600
    if (!empty($_FILES['user_upload']['name'])) {
2601
        $upload_ok = process_uploaded_file($_FILES['user_upload']);
2602
        $has_attachment = true;
2603
    }
2604
2605
    if (!$upload_ok) {
2606
        if ($showMessage) {
2607
            Display::addFlash(
2608
                Display::return_message(
2609
                    get_lang('UplNoFileUploaded'),
2610
                    'error',
2611
                    false
2612
                )
2613
            );
2614
        }
2615
2616
        return null;
2617
    }
2618
2619
    $post_date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
2620
2621
    if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
2622
        $visible = 0; // The post has not been approved yet.
2623
    } else {
2624
        $visible = 1;
2625
    }
2626
    $clean_post_title = $values['post_title'];
2627
    // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
2628
2629
    $lastThread = new CForumThread();
2630
    $lastThread
2631
        ->setCId($course_id)
2632
        ->setThreadTitle($clean_post_title)
2633
        ->setForumId($values['forum_id'])
2634
        ->setThreadPosterId($userId)
2635
        ->setThreadPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2636
        ->setThreadDate($post_date)
2637
        ->setThreadSticky(isset($values['thread_sticky']) ? $values['thread_sticky'] : 0)
0 ignored issues
show
Bug introduced by
It seems like IssetNode ? $values['thread_sticky'] : 0 can also be of type integer; however, parameter $threadSticky of Chamilo\CourseBundle\Ent...read::setThreadSticky() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2637
        ->setThreadSticky(/** @scrutinizer ignore-type */ isset($values['thread_sticky']) ? $values['thread_sticky'] : 0)
Loading history...
2638
        ->setThreadTitleQualify(
2639
            isset($values['calification_notebook_title']) ? $values['calification_notebook_title'] : null
2640
        )
2641
        ->setThreadQualifyMax(isset($values['numeric_calification']) ? (int) $values['numeric_calification'] : 0)
2642
        ->setThreadWeight(isset($values['weight_calification']) ? (int) $values['weight_calification'] : 0)
2643
        ->setThreadPeerQualify(isset($values['thread_peer_qualify']) ? (bool) $values['thread_peer_qualify'] : false)
2644
        ->setSessionId($sessionId)
2645
        ->setLpItemId(isset($values['lp_item_id']) ? (int) $values['lp_item_id'] : 0)
2646
        ->setThreadId(0)
2647
        ->setLocked(0)
2648
    ;
2649
2650
    $em->persist($lastThread);
2651
    $em->flush();
2652
2653
    // Add option gradebook qualify.
2654
    if (isset($values['thread_qualify_gradebook']) &&
2655
        1 == $values['thread_qualify_gradebook']
2656
    ) {
2657
        // Add function gradebook.
2658
        $resourcename = stripslashes($values['calification_notebook_title']);
2659
        GradebookUtils::add_resource_to_course_gradebook(
2660
            $values['category_id'],
2661
            $courseCode,
2662
            5,
2663
            $lastThread->getIid(),
2664
            $resourcename,
2665
            $values['weight_calification'],
2666
            $values['numeric_calification'],
2667
            '',
2668
            0,
2669
            $sessionId
2670
        );
2671
    }
2672
2673
    if ($lastThread->getIid()) {
2674
        $lastThread->setThreadId($lastThread->getIid());
2675
2676
        $em->merge($lastThread);
2677
        $em->flush();
2678
2679
        api_item_property_update(
2680
            $courseInfo,
2681
            TOOL_FORUM_THREAD,
2682
            $lastThread->getIid(),
2683
            'ForumThreadAdded',
2684
            $userId,
2685
            $groupInfo,
2686
            null,
2687
            null,
2688
            null,
2689
            $sessionId
2690
        );
2691
2692
        // If the forum properties tell that the posts have to be approved
2693
        // we have to put the whole thread invisible,
2694
        // because otherwise the students will see the thread and not the post
2695
        // in the thread.
2696
        // We also have to change $visible because the post itself has to be
2697
        // visible in this case (otherwise the teacher would have
2698
        // to make the thread visible AND the post.
2699
        // Default behaviour
2700
        api_set_default_visibility(
2701
            $lastThread->getIid(),
2702
            TOOL_FORUM_THREAD,
2703
            $groupId,
2704
            $courseInfo,
2705
            $sessionId,
2706
            $userId
2707
        );
2708
2709
        if ($visible == 0) {
2710
            api_item_property_update(
2711
                $courseInfo,
2712
                TOOL_FORUM_THREAD,
2713
                $lastThread->getIid(),
2714
                'invisible',
2715
                $userId,
2716
                $groupInfo
2717
            );
2718
            $visible = 1;
2719
        }
2720
    }
2721
2722
    // We now store the content in the table_post table.
2723
    $lastPost = new CForumPost();
2724
    $lastPost
2725
        ->setCId($course_id)
2726
        ->setPostTitle($clean_post_title)
2727
        ->setPostText($values['post_text'])
2728
        ->setThreadId($lastThread->getIid())
2729
        ->setForumId($values['forum_id'])
2730
        ->setPosterId($userId)
2731
        ->setPosterName(isset($values['poster_name']) ? $values['poster_name'] : null)
2732
        ->setPostDate($post_date)
2733
        ->setPostNotification(isset($values['post_notification']) ? (int) $values['post_notification'] : null)
0 ignored issues
show
Bug introduced by
It seems like IssetNode ? (int)$values...t_notification'] : null can also be of type integer; however, parameter $postNotification of Chamilo\CourseBundle\Ent...::setPostNotification() does only seem to accept boolean, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2733
        ->setPostNotification(/** @scrutinizer ignore-type */ isset($values['post_notification']) ? (int) $values['post_notification'] : null)
Loading history...
2734
        ->setPostParentId(null)
2735
        ->setVisible($visible)
2736
        ->setPostId(0)
2737
        ->setStatus(CForumPost::STATUS_VALIDATED);
2738
2739
    if ($current_forum['moderated']) {
2740
        $lastPost->setStatus(
2741
            api_is_course_admin() ? CForumPost::STATUS_VALIDATED : CForumPost::STATUS_WAITING_MODERATION
2742
        );
2743
    }
2744
2745
    $em->persist($lastPost);
2746
    $em->flush();
2747
2748
    $lastPostId = $lastPost->getIid();
2749
2750
    if ($lastPostId) {
2751
        $lastPost->setPostId($lastPostId);
2752
        $em->merge($lastPost);
2753
        $em->flush();
2754
    }
2755
2756
    // Update attached files
2757
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
2758
        foreach ($_POST['file_ids'] as $key => $id) {
2759
            editAttachedFile(
2760
                [
2761
                    'comment' => $_POST['file_comments'][$key],
2762
                    'post_id' => $lastPostId
2763
                ],
2764
                $id
2765
            );
2766
        }
2767
    }
2768
2769
    // Now we have to update the thread table to fill the thread_last_post
2770
    // field (so that we know when the thread has been updated for the last time).
2771
    $sql = "UPDATE $table_threads
2772
            SET thread_last_post = '".Database::escape_string($lastPostId)."'
2773
            WHERE
2774
                c_id = $course_id AND
2775
                thread_id='".Database::escape_string($lastThread->getIid())."'";
2776
    $result = Database::query($sql);
2777
    $message = get_lang('NewThreadStored');
2778
2779
    // Overwrite default message.
2780
    if ($current_forum['moderated'] &&
2781
        !api_is_allowed_to_edit(null, true)
2782
    ) {
2783
        $message = get_lang('MessageHasToBeApproved');
2784
    }
2785
2786
    // Storing the attachments if any.
2787
    if ($has_attachment) {
2788
        // Try to add an extension to the file if it hasn't one.
2789
        $new_file_name = add_ext_on_mime(
2790
            stripslashes($_FILES['user_upload']['name']),
2791
            $_FILES['user_upload']['type']
2792
        );
2793
2794
        if (!filter_extension($new_file_name)) {
2795
            if ($showMessage) {
2796
                Display::addFlash(Display::return_message(
2797
                    get_lang('UplUnableToSaveFileFilteredExtension'),
2798
                    'error'
2799
                ));
2800
            }
2801
        } else {
2802
            if ($result) {
2803
                add_forum_attachment_file(
2804
                    isset($values['file_comment']) ? $values['file_comment'] : null,
2805
                    $lastPostId
2806
                );
2807
            }
2808
        }
2809
    } else {
2810
        $message .= '<br />';
2811
    }
2812
2813
    if ($current_forum['approval_direct_post'] == '1' &&
2814
        !api_is_allowed_to_edit(null, true)
2815
    ) {
2816
        $message .= get_lang('MessageHasToBeApproved').'<br />';
2817
        $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
2818
            get_lang('Forum').'</a><br />';
2819
    } else {
2820
        $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.
2821
            get_lang('Forum').'</a><br />';
2822
        $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&thread='.$lastThread->getIid().'">'.
2823
            get_lang('Message').'</a>';
2824
    }
2825
    $reply_info['new_post_id'] = $lastPostId;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$reply_info was never initialized. Although not strictly required by PHP, it is generally a good practice to add $reply_info = array(); before regardless.
Loading history...
2826
    $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
2827
2828
    if ($my_post_notification == 1) {
2829
        set_notification('thread', $lastThread->getIid(), true);
2830
    }
2831
2832
    send_notification_mails(
2833
        $current_forum['forum_id'],
2834
        $lastThread->getIid(),
2835
        $reply_info,
2836
        $courseInfo['code']
2837
    );
2838
2839
    Session::erase('formelements');
2840
    Session::erase('origin');
2841
    Session::erase('breadcrumbs');
2842
    Session::erase('addedresource');
2843
    Session::erase('addedresourceid');
2844
2845
    if ($showMessage) {
2846
        Display::addFlash(Display::return_message($message, 'success', false));
2847
    }
2848
    return $lastThread->getIid();
2849
}
2850
2851
/**
2852
 * This function displays the form that is used to add a post. This can be a new thread or a reply.
2853
 * @param array $current_forum
2854
 * @param array $forum_setting
2855
 * @param string $action is the parameter that determines if we are
2856
 *  1. newthread: adding a new thread (both empty) => No I-frame
2857
 *  2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
2858
 *  3. replymessage: Replying to a message ($action =replymessage) => I-frame with the complete thread (if enabled)
2859
 * (I first thought to put and I-frame with the message only)
2860
 *  4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread (if enabled).
2861
 * The message will be in the reply. (I first thought not to put an I-frame here)
2862
 * @return FormValidator
2863
 * @author Patrick Cool <[email protected]>, Ghent University
2864
 * @version february 2006, dokeos 1.8
2865
 */
2866
function show_add_post_form($current_forum, $forum_setting, $action, $id = '', $form_values = '')
2867
{
2868
    $_user = api_get_user_info();
2869
    $action = isset($action) ? Security::remove_XSS($action) : '';
2870
    $myThread = isset($_GET['thread']) ? (int) $_GET['thread'] : '';
2871
    $forumId = isset($_GET['forum']) ? (int) $_GET['forum'] : '';
2872
    $my_post = isset($_GET['post']) ? (int) $_GET['post'] : '';
2873
2874
    $url = api_get_self().'?'.http_build_query([
2875
        'action' => $action,
2876
        'forum' => $forumId,
2877
        'thread' => $myThread,
2878
        'post' => $my_post
2879
    ]).'&'.api_get_cidreq();
2880
2881
    $form = new FormValidator(
2882
        'thread',
2883
        'post',
2884
        $url
2885
    );
2886
2887
    $form->setConstants(['forum' => '5']);
2888
2889
    // Setting the form elements.
2890
    $form->addElement('hidden', 'forum_id', $forumId);
2891
    $form->addElement('hidden', 'thread_id', $myThread);
2892
    $form->addElement('hidden', 'action', $action);
2893
2894
    // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
2895
    if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
2896
        $form->addElement('text', 'poster_name', get_lang('Name'));
2897
        $form->applyFilter('poster_name', 'html_filter');
2898
    }
2899
2900
    $form->addElement('text', 'post_title', get_lang('Title'));
2901
    $form->addHtmlEditor(
2902
        'post_text',
2903
        get_lang('Text'),
2904
        true,
2905
        false,
2906
        api_is_allowed_to_edit(null, true) ? [
2907
            'ToolbarSet' => 'Forum',
2908
            'Width' => '100%',
2909
            'Height' => '300',
2910
        ] : [
2911
            'ToolbarSet' => 'ForumStudent',
2912
            'Width' => '100%',
2913
            'Height' => '300',
2914
            'UserStatus' => 'student'
2915
        ]
2916
    );
2917
2918
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
2919
    $iframe = null;
2920
    $myThread = Security::remove_XSS($myThread);
2921
    if ($forum_setting['show_thread_iframe_on_reply'] && $action != 'newthread' && !empty($myThread)) {
2922
        $iframe = "<iframe style=\"border: 1px solid black\" src=\"iframe_thread.php?".api_get_cidreq()."&forum=".intval($forumId)."&thread=".$myThread."#".Security::remove_XSS($my_post)."\" width=\"100%\"></iframe>";
2923
    }
2924
    if (!empty($iframe)) {
2925
        $form->addElement('label', get_lang('Thread'), $iframe);
2926
    }
2927
2928
    if (Gradebook::is_active() &&
2929
        (api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor()) && !($myThread)
2930
    ) {
2931
        $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
2932
        $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
2933
2934
        // Thread qualify
2935
        if (Gradebook::is_active()) {
2936
            //Loading gradebook select
2937
            GradebookUtils::load_gradebook_select_in_tool($form);
2938
            $form->addElement(
2939
                'checkbox',
2940
                'thread_qualify_gradebook',
2941
                '',
2942
                get_lang('QualifyThreadGradebook'),
2943
                'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
2944
            );
2945
        } else {
2946
            $form->addElement('hidden', 'thread_qualify_gradebook', false);
2947
        }
2948
2949
        $form->addElement('html', '<div id="options_field" style="display:none">');
2950
        $form->addElement('text', 'numeric_calification', get_lang('QualificationNumeric'));
2951
        $form->applyFilter('numeric_calification', 'html_filter');
2952
        $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
2953
        $form->applyFilter('calification_notebook_title', 'html_filter');
2954
2955
        $form->addElement(
2956
            'text',
2957
            'weight_calification',
2958
            get_lang('QualifyWeight'),
2959
            ['value' => '0.00', 'onfocus' => "javascript: this.select();"]
2960
        );
2961
        $form->applyFilter('weight_calification', 'html_filter');
2962
2963
        $group = [];
2964
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
2965
        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
2966
        $form->addGroup(
2967
            $group,
2968
            '',
2969
            [
2970
                get_lang('ForumThreadPeerScoring'),
2971
                get_lang('ForumThreadPeerScoringComment'),
2972
            ]
2973
        );
2974
        $form->addElement('html', '</div>');
2975
        $form->addElement('html', '</div>');
2976
    }
2977
2978
    if ($forum_setting['allow_sticky'] && api_is_allowed_to_edit(null, true) && $action == 'newthread') {
2979
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
2980
    }
2981
2982
    if (in_array($action, ['quote', 'replymessage'])) {
2983
        $form->addFile('user_upload[]', get_lang('Attachment'));
2984
        $form->addButton(
2985
            'add_attachment',
2986
            get_lang('AddAttachment'),
2987
            'paperclip',
2988
            'default',
2989
            'default',
2990
            null,
2991
            ['id' => 'reply-add-attachment']
2992
        );
2993
    } else {
2994
        $form->addFile('user_upload', get_lang('Attachment'));
2995
    }
2996
2997
    // Setting the class and text of the form title and submit button.
2998
    if ($action == 'quote') {
2999
        $form->addButtonCreate(get_lang('QuoteMessage'), 'SubmitPost');
3000
    } elseif ($action == 'replythread') {
3001
        $form->addButtonCreate(get_lang('ReplyToThread'), 'SubmitPost');
3002
    } elseif ($action == 'replymessage') {
3003
        $form->addButtonCreate(get_lang('ReplyToMessage'), 'SubmitPost');
3004
    } else {
3005
        $form->addButtonCreate(get_lang('CreateThread'), 'SubmitPost');
3006
    }
3007
3008
    if (!empty($form_values)) {
3009
        $defaults['post_title'] = prepare4display($form_values['post_title']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$defaults was never initialized. Although not strictly required by PHP, it is generally a good practice to add $defaults = array(); before regardless.
Loading history...
3010
        $defaults['post_text'] = prepare4display($form_values['post_text']);
3011
        $defaults['post_notification'] = (int) $form_values['post_notification'];
3012
        $defaults['thread_sticky'] = (int) $form_values['thread_sticky'];
3013
        $defaults['thread_peer_qualify'] = (int) $form_values['thread_peer_qualify'];
3014
    } else {
3015
        $defaults['thread_peer_qualify'] = 0;
3016
    }
3017
3018
    // If we are quoting a message we have to retrieve the information of the post we are quoting so that
3019
    // we can add this as default to the textarea.
3020
    if (($action == 'quote' || $action == 'replymessage') && isset($my_post)) {
3021
        // We also need to put the parent_id of the post in a hidden form when
3022
        // we are quoting or replying to a message (<> reply to a thread !!!)
3023
        $form->addHidden('post_parent_id', intval($my_post));
3024
3025
        // If we are replying or are quoting then we display a default title.
3026
        $values = get_post_information($my_post);
0 ignored issues
show
Bug introduced by
It seems like $my_post can also be of type string; however, parameter $post_id of get_post_information() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3026
        $values = get_post_information(/** @scrutinizer ignore-type */ $my_post);
Loading history...
3027
        $posterInfo = api_get_user_info($values['poster_id']);
3028
        $posterName = '';
3029
        if ($posterInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $posterInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
3030
            $posterName = $posterInfo['complete_name'];
3031
        }
3032
        $defaults['post_title'] = get_lang('ReplyShort').api_html_entity_decode($values['post_title'], ENT_QUOTES);
3033
        // When we are quoting a message then we have to put that message into the wysiwyg editor.
3034
        // Note: The style has to be hardcoded here because using class="quote" didn't work.
3035
        if ($action == 'quote') {
3036
            $defaults['post_text'] = '<div>&nbsp;</div>
3037
                <div style="margin: 5px;">
3038
                    <div style="font-size: 90%; font-style: italic;">'.
3039
                        get_lang('Quoting').' '.$posterName.':</div>
3040
                        <div style="color: #006600; font-size: 90%;  font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.
3041
                            prepare4display($values['post_text']).'
3042
                        </div>
3043
                    </div>
3044
                <div>&nbsp;</div>
3045
                <div>&nbsp;</div>
3046
            ';
3047
        }
3048
    }
3049
3050
    $form->setDefaults(isset($defaults) ? $defaults : []);
3051
3052
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3053
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
3054
    if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
3055
        $form->addRule(
3056
            'poster_name',
3057
            get_lang('ThisFieldIsRequired'),
3058
            'required'
3059
        );
3060
    }
3061
3062
    // Validation or display
3063
    if ($form->validate()) {
3064
        $check = Security::check_token('post');
3065
        if ($check) {
3066
            $values = $form->exportValues();
3067
            if (isset($values['thread_qualify_gradebook']) &&
3068
                $values['thread_qualify_gradebook'] == '1' &&
3069
                empty($values['weight_calification'])
3070
            ) {
3071
                Display::addFlash(
3072
                    Display::return_message(
3073
                        get_lang('YouMustAssignWeightOfQualification').'&nbsp;<a href="javascript:window.history.go(-1);">'.get_lang('Back').'</a>',
3074
                        'error',
3075
                        false
3076
                    )
3077
                );
3078
3079
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type FormValidator.
Loading history...
3080
            }
3081
3082
            switch ($action) {
3083
                case 'newthread':
3084
                    $myThread = store_thread($current_forum, $values);
3085
                    break;
3086
                case 'quote':
3087
                case 'replythread':
3088
                case 'replymessage':
3089
                    store_reply($current_forum, $values);
3090
3091
                    break;
3092
            }
3093
3094
            $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&'.http_build_query(
3095
                [
3096
                    'forum' => $forumId,
3097
                    'thread' => $myThread
3098
                ]
3099
            );
3100
3101
            Security::clear_token();
3102
            header('Location: '.$url);
3103
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
3104
        }
3105
    } else {
3106
        $token = Security::get_token();
3107
        $form->addElement('hidden', 'sec_token');
3108
        $form->setConstants(['sec_token' => $token]);
3109
3110
        // Delete from $_SESSION forum attachment from other posts
3111
        // and keep only attachments for new post
3112
        clearAttachedFiles(FORUM_NEW_POST);
3113
        // Get forum attachment ajax table to add it to form
3114
        $attachmentAjaxTable = getAttachmentsAjaxTable(0, $current_forum['forum_id']);
3115
        $ajaxHtml = $attachmentAjaxTable;
3116
        $form->addElement('html', $ajaxHtml);
3117
3118
        return $form;
3119
    }
3120
}
3121
3122
/**
3123
 * @param array $threadInfo
3124
 * @param integer $user_id
3125
 * @param integer $thread_id
3126
 * @param integer $thread_qualify
3127
 * @param integer $qualify_time
3128
 * @param integer $session_id
3129
 * @return array optional
3130
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3131
 * @version October 2008, dokeos  1.8.6
3132
 */
3133
function saveThreadScore(
3134
    $threadInfo,
3135
    $user_id,
3136
    $thread_id,
3137
    $thread_qualify = 0,
3138
    $qualify_time,
3139
    $session_id = 0
3140
) {
3141
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3142
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3143
3144
    $course_id = api_get_course_int_id();
3145
    $session_id = intval($session_id);
3146
    $currentUserId = api_get_user_id();
3147
3148
    if ($user_id == strval(intval($user_id)) &&
3149
        $thread_id == strval(intval($thread_id)) &&
3150
        $thread_qualify == strval(floatval($thread_qualify))
3151
    ) {
3152
        // Testing
3153
        $sql = "SELECT thread_qualify_max FROM $table_threads
3154
                WHERE c_id = $course_id AND thread_id=".$thread_id;
3155
        $res_string = Database::query($sql);
3156
        $row_string = Database::fetch_array($res_string);
3157
        if ($thread_qualify <= $row_string[0]) {
3158
            if ($threadInfo['thread_peer_qualify'] == 0) {
3159
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3160
                        WHERE
3161
                            c_id = $course_id AND
3162
                            user_id = $user_id AND
3163
                            thread_id = ".$thread_id;
3164
            } else {
3165
                $sql = "SELECT COUNT(*) FROM $table_threads_qualify
3166
                        WHERE
3167
                            c_id = $course_id AND
3168
                            user_id = $user_id AND
3169
                            qualify_user_id = $currentUserId AND
3170
                            thread_id = ".$thread_id;
3171
            }
3172
3173
            $result = Database::query($sql);
3174
            $row = Database::fetch_array($result);
3175
3176
            if ($row[0] == 0) {
3177
                $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
3178
                        VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float) $thread_qualify.", '".$currentUserId."','".$qualify_time."','".$session_id."')";
3179
                Database::query($sql);
3180
                $insertId = Database::insert_id();
3181
                if ($insertId) {
3182
                    $sql = "UPDATE $table_threads_qualify SET id = iid
3183
                            WHERE iid = $insertId";
3184
                    Database::query($sql);
3185
                }
3186
3187
                return 'insert';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'insert' returns the type string which is incompatible with the documented return type array.
Loading history...
3188
            } else {
3189
                saveThreadScoreHistory(
3190
                    '1',
3191
                    $course_id,
3192
                    $user_id,
3193
                    $thread_id
3194
                );
3195
3196
                // Update
3197
                $sql = "UPDATE $table_threads_qualify
3198
                        SET
3199
                            qualify = '".$thread_qualify."',
3200
                            qualify_time = '".$qualify_time."'
3201
                        WHERE
3202
                            c_id = $course_id AND
3203
                            user_id=".$user_id." AND
3204
                            thread_id=".$thread_id." AND
3205
                            qualify_user_id = $currentUserId
3206
                        ";
3207
                Database::query($sql);
3208
3209
                return 'update';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'update' returns the type string which is incompatible with the documented return type array.
Loading history...
3210
            }
3211
        } else {
3212
            return null;
3213
        }
3214
    }
3215
}
3216
3217
/**
3218
 * This function shows qualify.
3219
 * @param string $option contains the information of option to run
3220
 * @param integer $user_id contains the information the current user id
3221
 * @param integer $thread_id contains the information the current thread id
3222
 * @return integer qualify
3223
 * <code> $option=1 obtained the qualification of the current thread</code>
3224
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3225
 * @version October 2008, dokeos  1.8.6
3226
 */
3227
function showQualify($option, $user_id, $thread_id)
3228
{
3229
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3230
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3231
3232
    $course_id = api_get_course_int_id();
3233
    $user_id = intval($user_id);
3234
    $thread_id = intval($thread_id);
3235
3236
    if (empty($user_id) || empty($thread_id)) {
3237
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
3238
    }
3239
3240
    $sql = '';
3241
    switch ($option) {
3242
        case 1:
3243
            $sql = "SELECT qualify FROM $table_threads_qualify
3244
                    WHERE
3245
                        c_id = $course_id AND
3246
                        user_id=".$user_id." AND
3247
                        thread_id=".$thread_id;
3248
            break;
3249
        case 2:
3250
            $sql = "SELECT thread_qualify_max FROM $table_threads
3251
                    WHERE c_id = $course_id AND thread_id=".$thread_id;
3252
            break;
3253
    }
3254
3255
    if (!empty($sql)) {
3256
        $rs = Database::query($sql);
3257
        $row = Database::fetch_array($rs);
3258
3259
        return $row[0];
3260
    }
3261
3262
    return [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return array() returns the type array which is incompatible with the documented return type integer.
Loading history...
3263
}
3264
3265
/**
3266
 * This function gets qualify historical.
3267
 * @param integer $user_id contains the information the current user id
3268
 * @param integer $thread_id contains the information the current thread id
3269
 * @param boolean $opt contains the information of option to run
3270
 * @return array
3271
 * @author Christian Fasanando <[email protected]>,
3272
 * @author Isaac Flores <[email protected]>,
3273
 * @version October 2008, dokeos  1.8.6
3274
 */
3275
function getThreadScoreHistory($user_id, $thread_id, $opt)
3276
{
3277
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3278
    $course_id = api_get_course_int_id();
3279
3280
    if ($opt == 'false') {
3281
        $sql = "SELECT * FROM $table_threads_qualify_log
3282
                WHERE
3283
                    c_id = $course_id AND
3284
                    thread_id='".Database::escape_string($thread_id)."' AND
3285
                    user_id='".Database::escape_string($user_id)."'
3286
                ORDER BY qualify_time";
3287
    } else {
3288
        $sql = "SELECT * FROM $table_threads_qualify_log
3289
                WHERE
3290
                    c_id = $course_id AND
3291
                    thread_id='".Database::escape_string($thread_id)."' AND
3292
                    user_id='".Database::escape_string($user_id)."'
3293
                ORDER BY qualify_time DESC";
3294
    }
3295
    $rs = Database::query($sql);
3296
    $log = [];
3297
    while ($row = Database::fetch_array($rs, 'ASSOC')) {
3298
        $log[] = $row;
3299
    }
3300
3301
    return $log;
3302
}
3303
3304
/**
3305
 * This function stores qualify historical.
3306
 * @param boolean contains the information of option to run
3307
 * @param string contains the information the current course id
3308
 * @param integer contains the information the current forum id
3309
 * @param integer contains the information the current user id
3310
 * @param integer contains the information the current thread id
3311
 * @param integer contains the information the current qualify
3312
 * @param string $option
3313
 * @param integer $course_id
3314
 * @param integer $user_id
3315
 * @param integer $thread_id
3316
 * @return void
3317
 * <code>$option=1 obtained the qualification of the current thread</code>
3318
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3319
 * @version October 2008, dokeos  1.8.6
3320
 */
3321
function saveThreadScoreHistory(
3322
    $option,
3323
    $course_id,
3324
    $user_id,
3325
    $thread_id
3326
) {
3327
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3328
    $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
3329
3330
    $course_id = intval($course_id);
3331
    $qualify_user_id = api_get_user_id();
3332
3333
    if ($user_id == strval(intval($user_id)) &&
3334
        $thread_id == strval(intval($thread_id)) && $option == 1
3335
    ) {
3336
        // Extract information of thread_qualify.
3337
        $sql = "SELECT qualify, qualify_time
3338
                FROM $table_threads_qualify
3339
                WHERE
3340
                    c_id = $course_id AND
3341
                    user_id = ".$user_id." AND
3342
                    thread_id = ".$thread_id." AND
3343
                    qualify_user_id = $qualify_user_id
3344
                ";
3345
        $rs = Database::query($sql);
3346
        $row = Database::fetch_array($rs);
3347
3348
        // Insert thread_historical.
3349
        $sql = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id, qualify, qualify_user_id,qualify_time,session_id)
3350
                VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float) $row[0].", '".$qualify_user_id."','".$row[1]."','')";
3351
        Database::query($sql);
3352
3353
        $insertId = Database::insert_id();
3354
        if ($insertId) {
3355
            $sql = "UPDATE $table_threads_qualify_log SET id = iid
3356
                    WHERE iid = $insertId";
3357
            Database::query($sql);
3358
        }
3359
    }
3360
}
3361
3362
/**
3363
 * This function shows current thread qualify .
3364
 * @param integer $threadId
3365
 * @param integer $sessionId
3366
 * @param integer $userId
3367
 *
3368
 * @return array or null if is empty
3369
 * @author Isaac Flores <[email protected]>, U.N.A.S University
3370
 * @version December 2008, dokeos  1.8.6
3371
 */
3372
function current_qualify_of_thread($threadId, $sessionId, $userId)
3373
{
3374
    $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
3375
3376
    $course_id = api_get_course_int_id();
3377
    $currentUserId = api_get_user_id();
3378
    $sessionId = intval($sessionId);
3379
    $threadId = intval($threadId);
3380
3381
    $sql = "SELECT qualify FROM $table_threads_qualify
3382
            WHERE
3383
                c_id = $course_id AND
3384
                thread_id = $threadId AND
3385
                session_id = $sessionId AND
3386
                qualify_user_id = $currentUserId AND
3387
                user_id = $userId
3388
            ";
3389
    $res = Database::query($sql);
3390
    $row = Database::fetch_array($res, 'ASSOC');
3391
3392
    return $row['qualify'];
3393
}
3394
3395
/**
3396
 * This function stores a reply in the forum_post table.
3397
 * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date)
3398
 * @param array $current_forum
3399
 * @param array $values
3400
 * @param int $courseId Optional
3401
 * @param int $userId Optional
3402
 * @return array
3403
 * @author Patrick Cool <[email protected]>, Ghent University
3404
 * @version february 2006, dokeos 1.8
3405
 */
3406
function store_reply($current_forum, $values, $courseId = 0, $userId = 0)
3407
{
3408
    $courseId = !empty($courseId) ? $courseId : api_get_course_int_id();
3409
    $_course = api_get_course_info_by_id($courseId);
3410
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3411
    $post_date = api_get_utc_datetime();
3412
    $userId = $userId ?: api_get_user_id();
3413
3414
    if ($current_forum['allow_anonymous'] == 1) {
3415
        if (api_is_anonymous() && empty($userId)) {
3416
            $userId = api_get_anonymous_id();
3417
        }
3418
    }
3419
3420
    if (empty($userId)) {
3421
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array.
Loading history...
3422
    }
3423
3424
    if ($current_forum['approval_direct_post'] == '1' &&
3425
        !api_is_allowed_to_edit(null, true)
3426
    ) {
3427
        $visible = 0;
3428
    } else {
3429
        $visible = 1;
3430
    }
3431
3432
    $upload_ok = 1;
3433
    $return = [];
3434
3435
    if ($upload_ok) {
3436
        // We first store an entry in the forum_post table.
3437
        $new_post_id = Database::insert(
3438
            $table_posts,
3439
            [
3440
                'c_id' => $courseId,
3441
                'post_title' => $values['post_title'],
3442
                'post_text' => isset($values['post_text']) ? ($values['post_text']) : null,
3443
                'thread_id' => $values['thread_id'],
3444
                'forum_id' => $values['forum_id'],
3445
                'poster_id' => $userId,
3446
                'post_id' => 0,
3447
                'post_date' => $post_date,
3448
                'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : null,
3449
                'post_parent_id' => isset($values['post_parent_id']) ? $values['post_parent_id'] : null,
3450
                'visible' => $visible,
3451
            ]
3452
        );
3453
3454
        if ($new_post_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_post_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
3455
            $sql = "UPDATE $table_posts SET post_id = iid WHERE iid = $new_post_id";
3456
            Database::query($sql);
3457
3458
            $values['new_post_id'] = $new_post_id;
3459
            $message = get_lang('ReplyAdded');
3460
3461
            if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3462
                foreach ($_POST['file_ids'] as $key => $id) {
3463
                    editAttachedFile(
3464
                        [
3465
                            'comment' => $_POST['file_comments'][$key],
3466
                            'post_id' => $new_post_id,
3467
                        ],
3468
                        $id
3469
                    );
3470
                }
3471
            }
3472
3473
            // Update the thread.
3474
            updateThreadInfo($values['thread_id'], $new_post_id, $post_date);
3475
3476
            // Update the forum.
3477
            api_item_property_update(
3478
                $_course,
3479
                TOOL_FORUM,
3480
                $values['forum_id'],
3481
                'NewMessageInForum',
3482
                $userId
3483
            );
3484
3485
            // Insert post
3486
            api_item_property_update(
3487
                $_course,
3488
                TOOL_FORUM_POST,
3489
                $new_post_id,
3490
                'NewPost',
3491
                $userId
3492
            );
3493
3494
            if ($current_forum['approval_direct_post'] == '1' &&
3495
                !api_is_allowed_to_edit(null, true)
3496
            ) {
3497
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3498
            }
3499
3500
            if ($current_forum['moderated'] &&
3501
                !api_is_allowed_to_edit(null, true)
3502
            ) {
3503
                $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
3504
            }
3505
3506
            // Setting the notification correctly.
3507
            $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
3508
            if ($my_post_notification == 1) {
3509
                set_notification('thread', $values['thread_id'], true);
3510
            }
3511
3512
            send_notification_mails(
3513
                $values['forum_id'],
3514
                $values['thread_id'],
3515
                $values
3516
            );
3517
            add_forum_attachment_file('', $new_post_id);
3518
        }
3519
3520
        Session::erase('formelements');
3521
        Session::erase('origin');
3522
        Session::erase('breadcrumbs');
3523
        Session::erase('addedresource');
3524
        Session::erase('addedresourceid');
3525
3526
        Display::addFlash(Display::return_message($message, 'confirmation', false));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.
Loading history...
3527
    } else {
3528
        Display::addFlash(
3529
            Display::return_message(
3530
                get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst'),
3531
                'error'
3532
            )
3533
        );
3534
    }
3535
3536
    return $return;
3537
}
3538
3539
/**
3540
 * This function displays the form that is used to edit a post. This can be a new thread or a reply.
3541
 * @param array contains all the information about the current post
3542
 * @param array contains all the information about the current thread
3543
 * @param array contains all info about the current forum (to check if attachments are allowed)
3544
 * @param array contains the default values to fill the form
3545
 * @return void
3546
 *
3547
 * @author Patrick Cool <[email protected]>, Ghent University
3548
 * @version february 2006, dokeos 1.8
3549
 */
3550
function show_edit_post_form(
3551
    $forum_setting,
3552
    $current_post,
3553
    $current_thread,
3554
    $current_forum,
3555
    $form_values = '',
3556
    $id_attach = 0
3557
) {
3558
    // Initialize the object.
3559
    $form = new FormValidator(
3560
        'edit_post',
3561
        'post',
3562
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.intval($_GET['post'])
3563
    );
3564
    $form->addElement('header', get_lang('EditPost'));
3565
    // Setting the form elements.
3566
    $form->addElement('hidden', 'post_id', $current_post['post_id']);
3567
    $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
3568
    $form->addElement('hidden', 'id_attach', $id_attach);
3569
3570
    if (empty($current_post['post_parent_id'])) {
3571
        $form->addElement('hidden', 'is_first_post_of_thread', '1');
3572
    }
3573
3574
    $form->addElement('text', 'post_title', get_lang('Title'));
3575
    $form->applyFilter('post_title', 'html_filter');
3576
    $form->addElement(
3577
        'html_editor',
3578
        'post_text',
3579
        get_lang('Text'),
3580
        null,
3581
        api_is_allowed_to_edit(null, true) ? [
3582
            'ToolbarSet' => 'Forum',
3583
            'Width' => '100%',
3584
            'Height' => '400',
3585
        ] : [
3586
            'ToolbarSet' => 'ForumStudent',
3587
            'Width' => '100%',
3588
            'Height' => '400',
3589
            'UserStatus' => 'student',
3590
        ]
3591
    );
3592
    $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
3593
3594
    $form->addButtonAdvancedSettings('advanced_params');
3595
    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
3596
3597
    if ($current_forum['moderated'] && api_is_allowed_to_edit(null, true)) {
3598
        $group = [];
3599
        $group[] = $form->createElement(
3600
            'radio',
3601
            'status',
3602
            null,
3603
            get_lang('Validated'),
3604
            1
3605
        );
3606
        $group[] = $form->createElement(
3607
            'radio',
3608
            'status',
3609
            null,
3610
            get_lang('WaitingModeration'),
3611
            2
3612
        );
3613
        $group[] = $form->createElement(
3614
            'radio',
3615
            'status',
3616
            null,
3617
            get_lang('Rejected'),
3618
            3
3619
        );
3620
        $form->addGroup($group, 'status', get_lang('Status'));
3621
    }
3622
3623
    $defaults['status']['status'] = isset($current_post['status']) && !empty($current_post['status']) ? $current_post['status'] : 2;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$defaults was never initialized. Although not strictly required by PHP, it is generally a good practice to add $defaults = array(); before regardless.
Loading history...
3624
3625
    if ($forum_setting['allow_post_notification']) {
3626
        $form->addElement(
3627
            'checkbox',
3628
            'post_notification',
3629
            '',
3630
            get_lang('NotifyByEmail').' ('.$current_post['email'].')'
3631
        );
3632
    }
3633
3634
    if ($forum_setting['allow_sticky'] &&
3635
        api_is_allowed_to_edit(null, true) &&
3636
        empty($current_post['post_parent_id'])
3637
    ) {
3638
        // The sticky checkbox only appears when it is the first post of a thread.
3639
        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
3640
        if ($current_thread['thread_sticky'] == 1) {
3641
            $defaults['thread_sticky'] = true;
3642
        }
3643
    }
3644
3645
    $form->addElement('html', '</div>');
3646
3647
    $form->addFile('user_upload[]', get_lang('Attachment'));
3648
    $form->addButton(
3649
        'add_attachment',
3650
        get_lang('AddAttachment'),
3651
        'paperclip',
3652
        'default',
3653
        'default',
3654
        null,
3655
        ['id' => 'reply-add-attachment']
3656
    );
3657
3658
    $form->addButtonUpdate(get_lang('Modify'), 'SubmitPost');
3659
3660
    // Setting the default values for the form elements.
3661
    $defaults['post_title'] = $current_post['post_title'];
3662
    $defaults['post_text'] = $current_post['post_text'];
3663
3664
    if ($current_post['post_notification'] == 1) {
3665
        $defaults['post_notification'] = true;
3666
    }
3667
3668
    if (!empty($form_values)) {
3669
        $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
3670
        $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
3671
    }
3672
3673
    $form->setDefaults($defaults);
3674
3675
    // The course admin can make a thread sticky (=appears with special icon and always on top).
3676
3677
    $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
3678
3679
    // Validation or display
3680
    if ($form->validate()) {
3681
        $values = $form->exportValues();
3682
        store_edit_post($current_forum, $values);
3683
    } else {
3684
        // Delete from $_SESSION forum attachment from other posts
3685
        clearAttachedFiles($current_post['post_id']);
3686
        // Get forum attachment ajax table to add it to form
3687
        $fileData = getAttachmentsAjaxTable($current_post['post_id'], $current_forum['forum_id']);
3688
        $form->addElement('html', $fileData);
3689
        $form->display();
3690
    }
3691
}
3692
3693
/**
3694
 * This function stores the edit of a post in the forum_post table.
3695
 *
3696
 * @param array
3697
 * @return void HTML
3698
 *
3699
 * @author Patrick Cool <[email protected]>, Ghent University
3700
 * @version february 2006, dokeos 1.8
3701
 */
3702
function store_edit_post($forumInfo, $values)
3703
{
3704
    $threadTable = Database::get_course_table(TABLE_FORUM_THREAD);
3705
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3706
    $course_id = api_get_course_int_id();
3707
3708
    //check if this post is the first of the thread
3709
    // First we check if the change affects the thread and if so we commit
3710
    // the changes (sticky and post_title=thread_title are relevant).
3711
3712
    $posts = getPosts($forumInfo, $values['thread_id']);
3713
    $first_post = null;
3714
    if (!empty($posts) && count($posts) > 0 && isset($posts[0])) {
3715
        $first_post = $posts[0];
3716
    }
3717
3718
    if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
3719
        // Simple edit
3720
        $params = [
3721
            'thread_title' => $values['post_title'],
3722
            'thread_sticky' => isset($values['thread_sticky']) ? $values['thread_sticky'] : 0,
3723
        ];
3724
        $where = ['c_id = ? AND thread_id = ?' => [$course_id, $values['thread_id']]];
3725
        Database::update($threadTable, $params, $where);
3726
    }
3727
3728
    $status = '';
3729
    $updateStatus = false;
3730
    if ($forumInfo['moderated']) {
3731
        if (api_is_allowed_to_edit(null, true)) {
3732
            $status = $values['status']['status'];
3733
            $updateStatus = true;
3734
        } else {
3735
            $status = CForumPost::STATUS_WAITING_MODERATION;
3736
            $updateStatus = true;
3737
        }
3738
    }
3739
3740
    // Update the post_title and the post_text.
3741
    $params = [
3742
        'post_title' => $values['post_title'],
3743
        'post_text' => $values['post_text'],
3744
        'post_notification' => isset($values['post_notification']) ? $values['post_notification'] : '',
3745
    ];
3746
3747
    if ($updateStatus) {
3748
        $params['status'] = $status;
3749
    }
3750
3751
    $where = ['c_id = ? AND post_id = ?' => [$course_id, $values['post_id']]];
3752
    Database::update($table_posts, $params, $where);
3753
3754
    // Update attached files
3755
    if (!empty($_POST['file_ids']) && is_array($_POST['file_ids'])) {
3756
        foreach ($_POST['file_ids'] as $key => $id) {
3757
            editAttachedFile(
3758
                [
3759
                    'comment' => $_POST['file_comments'][$key],
3760
                    'post_id' => $values['post_id'],
3761
                ],
3762
                $id
3763
            );
3764
        }
3765
    }
3766
3767
    if (!empty($values['remove_attach'])) {
3768
        delete_attachment($values['post_id']);
3769
    }
3770
3771
    if (empty($values['id_attach'])) {
3772
        add_forum_attachment_file(
3773
            isset($values['file_comment']) ? $values['file_comment'] : null,
3774
            $values['post_id']
3775
        );
3776
    } else {
3777
        edit_forum_attachment_file(
3778
            isset($values['file_comment']) ? $values['file_comment'] : null,
3779
            $values['post_id'],
3780
            $values['id_attach']
3781
        );
3782
    }
3783
3784
    $message = get_lang('EditPostStored').'<br />';
3785
    $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&">'.get_lang('Forum').'</a><br />';
3786
    $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.$values['thread_id'].'&post='.Security::remove_XSS($_GET['post']).'">'.get_lang('Message').'</a>';
3787
3788
    Session::erase('formelements');
3789
    Session::erase('origin');
3790
    Session::erase('breadcrumbs');
3791
    Session::erase('addedresource');
3792
    Session::erase('addedresourceid');
3793
3794
    echo Display::return_message($message, 'confirmation', false);
3795
}
3796
3797
/**
3798
 * This function displays the firstname and lastname of the user as a link to the user tool.
3799
 *
3800
 * @param string names
3801
 * @ in_title : title tootip
3802
 * @return string HTML
3803
 *
3804
 * @author Patrick Cool <[email protected]>, Ghent University
3805
 * @version february 2006, dokeos 1.8
3806
 */
3807
function display_user_link($user_id, $name, $origin = '', $in_title = '')
3808
{
3809
    if ($user_id != 0) {
3810
        $userInfo = api_get_user_info($user_id);
3811
3812
        return '<a href="'.$userInfo['profile_url'].'">'.Security::remove_XSS($userInfo['complete_name']).'</a>';
3813
    } else {
3814
        return $name.' ('.get_lang('Anonymous').')';
3815
    }
3816
}
3817
3818
/**
3819
 * This function displays the user image from the profile, with a link to the user's details.
3820
 * @param   int     User's database ID
3821
 * @param   string  User's name
3822
 * @param   string  the origin where the forum is called (example : learnpath)
3823
 * @return  string  An HTML with the anchor and the image of the user
3824
 * @author Julio Montoya <[email protected]>
3825
 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment User's at position 0 could not be parsed: Unknown type name 'User's' at position 0 in User's.
Loading history...
3826
function display_user_image($user_id, $name, $origin = '')
3827
{
3828
    $userInfo = api_get_user_info($user_id);
3829
    $link = '<a href="'.(!empty($origin) ? '#' : $userInfo['profile_url']).'" '.(!empty($origin) ? 'target="_self"' : '').'>';
3830
3831
    if ($user_id != 0) {
3832
        return $link.'<img src="'.$userInfo['avatar'].'"  alt="'.$name.'"  title="'.$name.'" /></a>';
3833
    } else {
3834
        return $link.Display::return_icon('unknown.jpg', $name).'</a>';
3835
    }
3836
}
3837
3838
/**
3839
 * The thread view counter gets increased every time someone looks at the thread
3840
 *
3841
 * @param int
3842
 * @return void
3843
 *
3844
 * @author Patrick Cool <[email protected]>, Ghent University
3845
 * @version february 2006, dokeos 1.8
3846
 */
3847
function increase_thread_view($thread_id)
3848
{
3849
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3850
    $course_id = api_get_course_int_id();
3851
3852
    $sql = "UPDATE $table_threads 
3853
            SET thread_views = thread_views + 1
3854
            WHERE 
3855
                c_id = $course_id AND  
3856
                thread_id = '".intval($thread_id)."'";
3857
    Database::query($sql);
3858
}
3859
3860
/**
3861
 * The relies counter gets increased every time somebody replies to the thread
3862
 *
3863
 * @author Patrick Cool <[email protected]>, Ghent University
3864
 * @version february 2006, dokeos 1.8
3865
 * @param string $lastPostId
3866
 * @param string $post_date
3867
 */
3868
function updateThreadInfo($thread_id, $lastPostId, $post_date)
3869
{
3870
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
3871
    $course_id = api_get_course_int_id();
3872
    $sql = "UPDATE $table_threads SET 
3873
            thread_replies = thread_replies+1,
3874
            thread_last_post = '".Database::escape_string($lastPostId)."',
3875
            thread_date = '".Database::escape_string($post_date)."'
3876
            WHERE 
3877
                c_id = $course_id AND  
3878
                thread_id='".Database::escape_string($thread_id)."'"; // this needs to be cleaned first
3879
    Database::query($sql);
3880
}
3881
3882
/**
3883
 * This function is used to find all the information about what's new in the forum tool
3884
 * @return void
3885
 *
3886
 * @author Patrick Cool <[email protected]>, Ghent University
3887
 * @version february 2006, dokeos 1.8
3888
 */
3889
function get_whats_new()
3890
{
3891
    $userId = api_get_user_id();
3892
    $course_id = api_get_course_int_id();
3893
3894
    if (empty($course_id) || empty($userId)) {
3895
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
3896
    }
3897
3898
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3899
    $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
3900
3901
    $tool = TOOL_FORUM;
3902
    $lastForumAccess = Session::read('last_forum_access');
3903
3904
    if (!$lastForumAccess) {
3905
        $sql = "SELECT * FROM $tracking_last_tool_access
3906
                WHERE
3907
                    access_user_id = $userId AND
3908
                    c_id = $course_id AND
3909
                    access_tool = '".Database::escape_string($tool)."'";
3910
        $result = Database::query($sql);
3911
        $row = Database::fetch_array($result);
3912
        Session::write('last_forum_access', $row['access_date']);
3913
        $lastForumAccess = $row['access_date'];
3914
    }
3915
3916
    $whatsNew = Session::read('whatsnew_post_info');
3917
3918
    if (!$whatsNew) {
3919
        if ($lastForumAccess != '') {
3920
            $postInfo = [];
3921
            $sql = "SELECT * FROM $table_posts
3922
                    WHERE
3923
                        c_id = $course_id AND
3924
                        visible = 1 AND                        
3925
                        post_date > '".Database::escape_string($lastForumAccess)."'";
3926
            $result = Database::query($sql);
3927
            while ($row = Database::fetch_array($result)) {
3928
                $postInfo[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
3929
            }
3930
            Session::write('whatsnew_post_info', $postInfo);
3931
        }
3932
    }
3933
}
3934
3935
/**
3936
 * This function approves a post = change
3937
 *
3938
 * @param int $post_id the id of the post that will be deleted
3939
 * @param string $action make the post visible or invisible
3940
 * @return string language variable
3941
 *
3942
 * @author Patrick Cool <[email protected]>, Ghent University
3943
 * @version february 2006, dokeos 1.8
3944
 */
3945
function approve_post($post_id, $action)
3946
{
3947
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3948
    $course_id = api_get_course_int_id();
3949
3950
    if ($action == 'invisible') {
3951
        $visibility_value = 0;
3952
    }
3953
3954
    if ($action == 'visible') {
3955
        $visibility_value = 1;
3956
        handle_mail_cue('post', $post_id);
3957
    }
3958
3959
    $sql = "UPDATE $table_posts SET
3960
            visible='".Database::escape_string($visibility_value)."'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $visibility_value does not seem to be defined for all execution paths leading up to this point.
Loading history...
3961
            WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
3962
    $return = Database::query($sql);
3963
3964
    if ($return) {
3965
        return 'PostVisibilityChanged';
3966
    }
3967
}
3968
3969
/**
3970
 * This function retrieves all the unapproved messages for a given forum
3971
 * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this)
3972
 *
3973
 * @param $forum_id the forum where we want to know the unapproved messages of
3974
 * @return array returns
3975
 *
3976
 * @author Patrick Cool <[email protected]>, Ghent University
3977
 * @version february 2006, dokeos 1.8
3978
 */
3979
function get_unaproved_messages($forum_id)
3980
{
3981
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
3982
    $course_id = api_get_course_int_id();
3983
3984
    $return_array = [];
3985
    $sql = "SELECT DISTINCT thread_id FROM $table_posts
3986
            WHERE 
3987
                c_id = $course_id AND 
3988
                forum_id='".Database::escape_string($forum_id)."' AND 
3989
                visible='0' ";
3990
    $result = Database::query($sql);
3991
    while ($row = Database::fetch_array($result)) {
3992
        $return_array[] = $row['thread_id'];
3993
    }
3994
3995
    return $return_array;
3996
}
3997
3998
/**
3999
 * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
4000
 * was added to a given thread.
4001
 *
4002
 * @param array reply information
4003
 * @return void
4004
 *
4005
 * @author Patrick Cool <[email protected]>, Ghent University
4006
 * @version february 2006, dokeos 1.8
4007
 */
4008
function send_notification_mails($forumId, $thread_id, $reply_info)
4009
{
4010
    $table = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4011
4012
    // First we need to check if
4013
    // 1. the forum category is visible
4014
    // 2. the forum is visible
4015
    // 3. the thread is visible
4016
    // 4. the reply is visible (=when there is)
4017
    $current_thread = get_thread_information($forumId, $thread_id);
4018
    $current_forum = get_forum_information($current_thread['forum_id'], $current_thread['c_id']);
0 ignored issues
show
Deprecated Code introduced by
The function get_forum_information() has been deprecated: this functionality is now moved to get_forums($forum_id) ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

4018
    $current_forum = /** @scrutinizer ignore-deprecated */ get_forum_information($current_thread['forum_id'], $current_thread['c_id']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
4019
4020
    $current_forum_category = null;
4021
    if (isset($current_forum['forum_category'])) {
4022
        $current_forum_category = get_forumcategory_information(
4023
            $current_forum['forum_category']
4024
        );
4025
    }
4026
4027
    if ($current_thread['visibility'] == '1' &&
4028
        $current_forum['visibility'] == '1' &&
4029
        ($current_forum_category && $current_forum_category['visibility'] == '1') &&
4030
        $current_forum['approval_direct_post'] != '1'
4031
    ) {
4032
        $send_mails = true;
4033
    } else {
4034
        $send_mails = false;
4035
    }
4036
4037
    // The forum category, the forum, the thread and the reply are visible to the user
4038
    if ($send_mails) {
4039
        if (!empty($forumId)) {
4040
            send_notifications($forumId, $thread_id);
4041
        }
4042
    } else {
4043
        $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
4044
        if (isset($current_forum['forum_id'])) {
4045
            $sql = "SELECT * FROM $table_notification
4046
                    WHERE
4047
                        c_id = ".api_get_course_int_id()." AND
4048
                        (
4049
                            forum_id = '".intval($current_forum['forum_id'])."' OR
4050
                            thread_id = '".intval($thread_id)."'
4051
                        ) ";
4052
4053
            $result = Database::query($sql);
4054
            $user_id = api_get_user_id();
4055
            while ($row = Database::fetch_array($result)) {
4056
                $sql = "INSERT INTO $table (c_id, thread_id, post_id, user_id)
4057
                        VALUES (".api_get_course_int_id().", '".intval($thread_id)."', '".intval($reply_info['new_post_id'])."', '$user_id' )";
4058
                Database::query($sql);
4059
            }
4060
        }
4061
    }
4062
}
4063
4064
/**
4065
 * This function is called whenever something is made visible because there might
4066
 * be new posts and the user might have indicated that (s)he wanted to be
4067
 * informed about the new posts by mail.
4068
 *
4069
 * @param string  Content type (post, thread, forum, forum_category)
4070
 * @param int     Item DB ID
4071
 * @param string $content
4072
 * @param integer $id
4073
 * @return string language variable
4074
 * @author Patrick Cool <[email protected]>, Ghent University
4075
 * @version february 2006, dokeos 1.8
4076
 */
4077
function handle_mail_cue($content, $id)
4078
{
4079
    $table_mailcue = Database::get_course_table(TABLE_FORUM_MAIL_QUEUE);
4080
    $table_forums = Database::get_course_table(TABLE_FORUM);
4081
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4082
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4083
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
4084
4085
    $course_id = api_get_course_int_id();
4086
4087
    /* If the post is made visible we only have to send mails to the people
4088
     who indicated that they wanted to be informed for that thread.*/
4089
    if ($content == 'post') {
4090
        // Getting the information about the post (need the thread_id).
4091
        $post_info = get_post_information($id);
4092
        $thread_id = intval($post_info['thread_id']);
4093
4094
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4095
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
4096
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4097
                WHERE
4098
                    posts.c_id = $course_id AND
4099
                    mailcue.c_id = $course_id AND
4100
                    posts.thread_id='$thread_id'
4101
                    AND posts.post_notification='1'
4102
                    AND mailcue.thread_id='$thread_id'
4103
                    AND users.user_id=posts.poster_id
4104
                    AND users.active=1
4105
                GROUP BY users.email";
4106
4107
        $result = Database::query($sql);
4108
        while ($row = Database::fetch_array($result)) {
4109
            send_mail($row, get_thread_information($post_info['forum_id'], $post_info['thread_id']));
4110
        }
4111
    } elseif ($content == 'thread') {
4112
        // Sending the mail to all the users that wanted to be informed for replies on this thread.
4113
        $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email, posts.forum_id
4114
                FROM $table_mailcue mailcue, $table_posts posts, $table_users users
4115
                WHERE
4116
                    posts.c_id = $course_id AND
4117
                    mailcue.c_id = $course_id AND
4118
                    posts.thread_id = ".intval($id)."
4119
                    AND posts.post_notification='1'
4120
                    AND mailcue.thread_id = ".intval($id)."
4121
                    AND users.user_id=posts.poster_id
4122
                    AND users.active=1
4123
                GROUP BY users.email";
4124
        $result = Database::query($sql);
4125
        while ($row = Database::fetch_array($result)) {
4126
            send_mail($row, get_thread_information($row['forum_id'], $id));
4127
        }
4128
4129
        // Deleting the relevant entries from the mailcue.
4130
        $sql = "DELETE FROM $table_mailcue
4131
                WHERE c_id = $course_id AND thread_id='".Database::escape_string($id)."'";
4132
        Database::query($sql);
4133
    } elseif ($content == 'forum') {
4134
        $sql = "SELECT thread_id FROM $table_threads
4135
                WHERE c_id = $course_id AND forum_id='".Database::escape_string($id)."'";
4136
        $result = Database::query($sql);
4137
        while ($row = Database::fetch_array($result)) {
4138
            handle_mail_cue('thread', $row['thread_id']);
4139
        }
4140
    } elseif ($content == 'forum_category') {
4141
        $sql = "SELECT forum_id FROM $table_forums
4142
                WHERE c_id = $course_id AND forum_category ='".Database::escape_string($id)."'";
4143
        $result = Database::query($sql);
4144
        while ($row = Database::fetch_array($result)) {
4145
            handle_mail_cue('forum', $row['forum_id']);
4146
        }
4147
    } else {
4148
        return get_lang('Error');
4149
    }
4150
}
4151
4152
/**
4153
 * This function sends the mails for the mail notification
4154
 *
4155
 * @param array
4156
 * @param array
4157
 * @return void
4158
 *
4159
 * @author Patrick Cool <[email protected]>, Ghent University
4160
 * @version february 2006, dokeos 1.8
4161
 */
4162
function send_mail($user_info = [], $thread_information = [])
4163
{
4164
    $_course = api_get_course_info();
4165
    $user_id = api_get_user_id();
4166
    $subject = get_lang('NewForumPost').' - '.$_course['official_code'];
4167
    if (isset($thread_information) && is_array($thread_information)) {
4168
        $thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&forum='.$thread_information['forum_id'].'&thread='.$thread_information['thread_id'];
4169
    }
4170
    $email_body = get_lang('Dear').' '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
4171
    $email_body .= get_lang('NewForumPost')."\n";
4172
    $email_body .= get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
4173
    $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
4174
    $email_body .= get_lang('ThreadCanBeFoundHere')." : <br /><a href=\"".$thread_link."\">".$thread_link."</a>\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $thread_link does not seem to be defined for all execution paths leading up to this point.
Loading history...
4175
4176
    if ($user_info['user_id'] <> $user_id) {
4177
        MessageManager::send_message(
4178
            $user_info['user_id'],
4179
            $subject,
4180
            $email_body,
4181
            [],
4182
            [],
4183
            null,
4184
            null,
4185
            null,
4186
            null,
4187
            $user_id
4188
        );
4189
    }
4190
}
4191
4192
/**
4193
 * This function displays the form for moving a thread to a different (already existing) forum
4194
 * @return void HTML
4195
 *
4196
 * @author Patrick Cool <[email protected]>, Ghent University
4197
 * @version february 2006, dokeos 1.8
4198
 */
4199
function move_thread_form()
4200
{
4201
    $form = new FormValidator(
4202
        'movepost',
4203
        'post',
4204
        api_get_self().'?forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&'.api_get_cidreq()
4205
    );
4206
    // The header for the form
4207
    $form->addElement('header', get_lang('MoveThread'));
4208
    // Invisible form: the thread_id
4209
    $form->addElement('hidden', 'thread_id', intval($_GET['thread']));
4210
    // the fora
4211
    $forum_categories = get_forum_categories();
4212
    $forums = get_forums();
4213
4214
    $htmlcontent = '<div class="row">
4215
        <div class="label">
4216
            <span class="form_required">*</span>'.get_lang('MoveTo').'
4217
        </div>
4218
        <div class="formw">';
4219
    $htmlcontent .= '<select name="forum">';
4220
    foreach ($forum_categories as $key => $category) {
4221
        $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
4222
        foreach ($forums as $key => $forum) {
4223
            if (isset($forum['forum_category'])) {
4224
                if ($forum['forum_category'] == $category['cat_id']) {
4225
                    $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
4226
                }
4227
            }
4228
        }
4229
        $htmlcontent .= '</optgroup>';
4230
    }
4231
    $htmlcontent .= "</select>";
4232
    $htmlcontent .= '   </div>
4233
                    </div>';
4234
4235
    $form->addElement('html', $htmlcontent);
4236
4237
    // The OK button
4238
    $form->addButtonSave(get_lang('MoveThread'), 'SubmitForum');
4239
4240
    // Validation or display
4241
    if ($form->validate()) {
4242
        $values = $form->exportValues();
4243
        if (isset($_POST['forum'])) {
4244
            store_move_thread($values);
4245
        }
4246
    } else {
4247
        $form->display();
4248
    }
4249
}
4250
4251
/**
4252
 * This function displays the form for moving a post message to a different (already existing) or a new thread.
4253
 *
4254
 * @author Patrick Cool <[email protected]>, Ghent University
4255
 * @version february 2006, dokeos 1.8
4256
 */
4257
function move_post_form()
4258
{
4259
    $form = new FormValidator(
4260
        'movepost',
4261
        'post',
4262
        api_get_self().'?'.api_get_cidreq().'&forum='.intval($_GET['forum']).'&thread='.intval($_GET['thread']).'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post'])
4263
    );
4264
    // The header for the form
4265
    $form->addElement('header', '', get_lang('MovePost'));
4266
4267
    // Invisible form: the post_id
4268
    $form->addElement('hidden', 'post_id', intval($_GET['post']));
4269
4270
    // Dropdown list: Threads of this forum
4271
    $threads = get_threads($_GET['forum']);
4272
    //my_print_r($threads);
4273
    $threads_list[0] = get_lang('ANewThread');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$threads_list was never initialized. Although not strictly required by PHP, it is generally a good practice to add $threads_list = array(); before regardless.
Loading history...
4274
    foreach ($threads as $key => $value) {
4275
        $threads_list[$value['thread_id']] = $value['thread_title'];
4276
    }
4277
    $form->addElement('select', 'thread', get_lang('MoveToThread'), $threads_list);
4278
    $form->applyFilter('thread', 'html_filter');
4279
4280
    // The OK button
4281
    $form->addButtonSave(get_lang('MovePost'), 'submit');
4282
4283
    // Setting the rules
4284
    $form->addRule('thread', get_lang('ThisFieldIsRequired'), 'required');
4285
4286
    // Validation or display
4287
    if ($form->validate()) {
4288
        $values = $form->exportValues();
4289
        store_move_post($values);
4290
    } else {
4291
        $form->display();
4292
    }
4293
}
4294
4295
/**
4296
 *
4297
 * @param array
4298
 * @return string HTML language variable
4299
 *
4300
 * @author Patrick Cool <[email protected]>, Ghent University
4301
 * @version february 2006, dokeos 1.8
4302
 */
4303
function store_move_post($values)
4304
{
4305
    $_course = api_get_course_info();
4306
    $course_id = api_get_course_int_id();
4307
4308
    $table_forums = Database::get_course_table(TABLE_FORUM);
4309
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4310
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4311
4312
    if ($values['thread'] == '0') {
4313
        $current_post = get_post_information($values['post_id']);
4314
4315
        // Storing a new thread.
4316
        $params = [
4317
            'c_id' => $course_id,
4318
            'thread_title' => $current_post['post_title'],
4319
            'forum_id' => $current_post['forum_id'],
4320
            'thread_poster_id' => $current_post['poster_id'],
4321
            'thread_poster_name' => $current_post['poster_name'],
4322
            'thread_last_post' => $values['post_id'],
4323
            'thread_date' => $current_post['post_date'],
4324
        ];
4325
4326
        $new_thread_id = Database::insert($table_threads, $params);
4327
4328
        api_item_property_update(
4329
            $_course,
4330
            TOOL_FORUM_THREAD,
4331
            $new_thread_id,
0 ignored issues
show
Bug introduced by
It seems like $new_thread_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4331
            /** @scrutinizer ignore-type */ $new_thread_id,
Loading history...
4332
            'visible',
4333
            $current_post['poster_id']
4334
        );
4335
4336
        // Moving the post to the newly created thread.
4337
        $sql = "UPDATE $table_posts SET thread_id='".intval($new_thread_id)."', post_parent_id = NULL
4338
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4339
        Database::query($sql);
4340
4341
        // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
4342
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4343
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4344
        Database::query($sql);
4345
4346
        // Updating updating the number of threads in the forum.
4347
        $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1
4348
                WHERE c_id = $course_id AND forum_id='".intval($current_post['forum_id'])."'";
4349
        Database::query($sql);
4350
4351
        // Resetting the last post of the old thread and decreasing the number of replies and the thread.
4352
        $sql = "SELECT * FROM $table_posts
4353
                WHERE c_id = $course_id AND thread_id='".intval($current_post['thread_id'])."'
4354
                ORDER BY post_id DESC";
4355
        $result = Database::query($sql);
4356
        $row = Database::fetch_array($result);
4357
        $sql = "UPDATE $table_threads SET
4358
                    thread_last_post='".$row['post_id']."',
4359
                    thread_replies=thread_replies-1
4360
                WHERE
4361
                    c_id = $course_id AND
4362
                    thread_id='".intval($current_post['thread_id'])."'";
4363
        Database::query($sql);
4364
    } else {
4365
        // Moving to the chosen thread.
4366
        $sql = "SELECT thread_id FROM ".$table_posts."
4367
                WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
4368
        $result = Database::query($sql);
4369
        $row = Database::fetch_array($result);
4370
4371
        $original_thread_id = $row['thread_id'];
4372
4373
        $sql = "SELECT thread_last_post FROM ".$table_threads."
4374
                WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4375
4376
        $result = Database::query($sql);
4377
        $row = Database::fetch_array($result);
4378
        $thread_is_last_post = $row['thread_last_post'];
4379
        // If is this thread, update the thread_last_post with the last one.
4380
4381
        if ($thread_is_last_post == $values['post_id']) {
4382
            $sql = "SELECT post_id FROM ".$table_posts."
4383
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."'
4384
                    ORDER BY post_date DESC LIMIT 1";
4385
            $result = Database::query($sql);
4386
4387
            $row = Database::fetch_array($result);
4388
            $thread_new_last_post = $row['post_id'];
4389
4390
            $sql = "UPDATE ".$table_threads." SET thread_last_post = '".$thread_new_last_post."'
4391
                    WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
4392
            Database::query($sql);
4393
        }
4394
4395
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1
4396
                WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
4397
        Database::query($sql);
4398
4399
        // moving to the chosen thread
4400
        $sql = "UPDATE $table_posts SET thread_id='".intval($_POST['thread'])."', post_parent_id = NULL
4401
                WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
4402
        Database::query($sql);
4403
4404
        // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
4405
        $sql = "UPDATE $table_posts SET post_parent_id = NULL
4406
                WHERE c_id = $course_id AND post_parent_id='".intval($values['post_id'])."'";
4407
        Database::query($sql);
4408
4409
        $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1
4410
                WHERE c_id = $course_id AND thread_id='".intval($_POST['thread'])."'";
4411
        Database::query($sql);
4412
    }
4413
4414
    return get_lang('ThreadMoved');
4415
}
4416
4417
/**
4418
 *
4419
 * @param array
4420
 * @return string HTML language variable
4421
 *
4422
 * @author Patrick Cool <[email protected]>, Ghent University
4423
 * @version february 2006, dokeos 1.8
4424
 */
4425
function store_move_thread($values)
4426
{
4427
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4428
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4429
4430
    $courseId = api_get_course_int_id();
4431
    $sessionId = api_get_session_id();
4432
4433
    $forumId = intval($_POST['forum']);
4434
    $threadId = intval($_POST['thread_id']);
4435
    $forumInfo = get_forums($forumId);
4436
4437
    // Change the thread table: Setting the forum_id to the new forum.
4438
    $sql = "UPDATE $table_threads SET forum_id = $forumId
4439
            WHERE c_id = $courseId AND thread_id = $threadId";
4440
    Database::query($sql);
4441
4442
    // Changing all the posts of the thread: setting the forum_id to the new forum.
4443
    $sql = "UPDATE $table_posts SET forum_id = $forumId
4444
            WHERE c_id = $courseId AND thread_id= $threadId";
4445
    Database::query($sql);
4446
    // Fix group id, if forum is moved to a different group
4447
    if (!empty($forumInfo['to_group_id'])) {
4448
        $groupId = $forumInfo['to_group_id'];
4449
        $item = api_get_item_property_info(
4450
            $courseId,
4451
            TABLE_FORUM_THREAD,
4452
            $threadId,
4453
            $sessionId,
4454
            $groupId
4455
        );
4456
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
4457
        $sessionCondition = api_get_session_condition($sessionId);
4458
4459
        if (!empty($item)) {
4460
            if ($item['to_group_id'] != $groupId) {
4461
                $sql = "UPDATE $table
4462
                    SET to_group_id = $groupId
4463
                    WHERE
4464
                      tool = '".TABLE_FORUM_THREAD."' AND
4465
                      c_id = $courseId AND
4466
                      ref = ".$item['ref']."
4467
                      $sessionCondition
4468
                ";
4469
                Database::query($sql);
4470
            }
4471
        } else {
4472
            $sql = "UPDATE $table
4473
                    SET to_group_id = $groupId
4474
                    WHERE
4475
                      tool = '".TABLE_FORUM_THREAD."' AND
4476
                      c_id = $courseId AND
4477
                      ref = ".$threadId."
4478
                      $sessionCondition
4479
            ";
4480
            Database::query($sql);
4481
        }
4482
    }
4483
4484
    return get_lang('ThreadMoved');
4485
}
4486
4487
/**
4488
 * Prepares a string for displaying by highlighting the search results inside, if any.
4489
 * @param string $input    The input string.
4490
 * @return string          The same string with highlighted hits inside.
4491
 *
4492
 * @author Patrick Cool <[email protected]>, Ghent University, February 2006 - the initial version.
4493
 * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
4494
 */
4495
function prepare4display($input)
4496
{
4497
    static $highlightcolors = ['yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33'];
4498
    static $search;
4499
4500
    if (!isset($search)) {
4501
        if (isset($_POST['search_term'])) {
4502
            $search = $_POST['search_term']; // No html at all.
4503
        } elseif (isset($_GET['search'])) {
4504
            $search = $_GET['search'];
4505
        } else {
4506
            $search = '';
4507
        }
4508
    }
4509
4510
    if (!empty($search)) {
4511
        if (strstr($search, '+')) {
4512
            $search_terms = explode('+', $search);
4513
        } else {
4514
            $search_terms[] = trim($search);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$search_terms was never initialized. Although not strictly required by PHP, it is generally a good practice to add $search_terms = array(); before regardless.
Loading history...
4515
        }
4516
        $counter = 0;
4517
        foreach ($search_terms as $key => $search_term) {
4518
            $input = api_preg_replace(
4519
                '/'.preg_quote(trim($search_term), '/').'/i',
4520
                '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
4521
                $input
4522
            );
4523
            $counter++;
4524
        }
4525
    }
4526
4527
    // TODO: Security should be implemented outside this function.
4528
    // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles
4529
    // (see comments of Security::remove_XSS() method to learn about other levels).
4530
4531
    return Security::remove_XSS($input, STUDENT, true);
4532
}
4533
4534
/**
4535
 * Display the search form for the forum and display the search results
4536
 * @return void display an HTML search results
4537
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4538
 * @version march 2008, dokeos 1.8.5
4539
 */
4540
function forum_search()
4541
{
4542
    $form = new FormValidator(
4543
        'forumsearch',
4544
        'post',
4545
        'forumsearch.php?'.api_get_cidreq()
4546
    );
4547
4548
    // Setting the form elements.
4549
    $form->addElement('header', '', get_lang('ForumSearch'));
4550
    $form->addElement('text', 'search_term', get_lang('SearchTerm'), ['autofocus']);
4551
    $form->applyFilter('search_term', 'html_filter');
4552
    $form->addElement('static', 'search_information', '', get_lang('ForumSearchInformation'));
4553
    $form->addButtonSearch(get_lang('Search'));
4554
4555
    // Setting the rules.
4556
    $form->addRule('search_term', get_lang('ThisFieldIsRequired'), 'required');
4557
    $form->addRule('search_term', get_lang('TooShort'), 'minlength', 3);
4558
4559
    // Validation or display.
4560
    if ($form->validate()) {
4561
        $values = $form->exportValues();
4562
        $form->setDefaults($values);
4563
        $form->display();
4564
        // Display the search results.
4565
        display_forum_search_results(stripslashes($values['search_term']));
4566
    } else {
4567
        $form->display();
4568
    }
4569
}
4570
4571
/**
4572
 * Display the search results
4573
 * @param string
4574
 * @param string $search_term
4575
 * @return void display the results
4576
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4577
 * @version march 2008, dokeos 1.8.5
4578
 */
4579
function display_forum_search_results($search_term)
4580
{
4581
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
4582
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
4583
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
4584
    $session_id = api_get_session_id();
4585
    $course_id = api_get_course_int_id();
4586
4587
    // Defining the search strings as an array.
4588
    if (strstr($search_term, '+')) {
4589
        $search_terms = explode('+', $search_term);
4590
    } else {
4591
        $search_terms[] = $search_term;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$search_terms was never initialized. Although not strictly required by PHP, it is generally a good practice to add $search_terms = array(); before regardless.
Loading history...
4592
    }
4593
4594
    // Search restriction.
4595
    foreach ($search_terms as $value) {
4596
        $search_restriction[] = "
4597
        (
4598
            posts.post_title LIKE '%".Database::escape_string(trim($value))."%' OR 
4599
            posts.post_text LIKE '%".Database::escape_string(trim($value))."%' 
4600
        )";
4601
    }
4602
4603
    $sessionCondition = api_get_session_condition(
4604
        $session_id,
4605
        true,
4606
        false,
4607
        'item_property.session_id'
4608
    );
4609
4610
    $sql = "SELECT posts.*
4611
            FROM $table_posts posts 
4612
            INNER JOIN $table_threads threads
4613
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
4614
            INNER JOIN $table_item_property item_property
4615
            ON (item_property.ref = threads.thread_id AND item_property.c_id = threads.c_id)
4616
            WHERE
4617
                posts.c_id = $course_id AND 
4618
                item_property.c_id = $course_id AND 
4619
                item_property.visibility = 1  
4620
                $sessionCondition AND
4621
                posts.visible = 1 AND 
4622
                item_property.tool = '".TOOL_FORUM_THREAD."' AND 
4623
                ".implode(' AND ', $search_restriction)."
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $search_restriction seems to be defined by a foreach iteration on line 4595. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
4624
            GROUP BY posts.post_id";
4625
4626
    // Getting all the information of the forum categories.
4627
    $forum_categories_list = get_forum_categories();
4628
4629
    // Getting all the information of the forums.
4630
    $forum_list = get_forums();
4631
4632
    $result = Database::query($sql);
4633
    $search_results = [];
4634
    while ($row = Database::fetch_array($result, 'ASSOC')) {
4635
        $forumId = $row['forum_id'];
4636
        $forumData = get_forums($forumId);
4637
        $category = isset($forum_categories_list[$forumData['forum_category']]) ? $forum_categories_list[$forumData['forum_category']] : null;
4638
        $display_result = false;
4639
        /*
4640
          We only show it when
4641
          1. forum category is visible
4642
          2. forum is visible
4643
          3. thread is visible (to do)
4644
          4. post is visible
4645
         */
4646
        if (!api_is_allowed_to_edit(null, true)) {
4647
            if (!empty($category)) {
4648
                if ($category['visibility'] == '1' && $forumData['visibility'] == '1') {
4649
                    $display_result = true;
4650
                }
4651
            } else {
4652
                if ($forumData['visible'] == '1') {
4653
                    $display_result = true;
4654
                }
4655
            }
4656
        } else {
4657
            $display_result = true;
4658
        }
4659
4660
        if ($display_result) {
4661
            $categoryName = !empty($category) ? $category['cat_title'] : '';
4662
            $search_results_item = '<li><a href="viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$forumData['forum_category'].'&search='.urlencode($search_term).'">'.
4663
                prepare4display($categoryName).'</a> &gt; ';
4664
            $search_results_item .= '<a href="viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.urlencode($search_term).'">'.
4665
                prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
4666
            $search_results_item .= '<a href="viewthread.php?'.api_get_cidreq().'&forum='.$forumId.'&thread='.$row['thread_id'].'&search='.urlencode($search_term).'">'.
4667
                prepare4display($row['post_title']).'</a>';
4668
            $search_results_item .= '<br />';
4669
            if (api_strlen($row['post_title']) > 200) {
4670
                $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
4671
            } else {
4672
                $search_results_item .= prepare4display($row['post_title']);
4673
            }
4674
            $search_results_item .= '</li>';
4675
            $search_results[] = $search_results_item;
4676
        }
4677
    }
4678
    echo '<legend>'.count($search_results).' '.get_lang('ForumSearchResults').'</legend>';
4679
    echo '<ol>';
4680
    if ($search_results) {
4681
        echo implode($search_results);
0 ignored issues
show
Bug introduced by
The call to implode() has too few arguments starting with pieces. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

4681
        echo /** @scrutinizer ignore-call */ implode($search_results);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
4682
    }
4683
    echo '</ol>';
4684
}
4685
4686
/**
4687
 * Return the link to the forum search page
4688
 *
4689
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
4690
 * @version April 2008, dokeos 1.8.5
4691
 */
4692
function search_link()
4693
{
4694
    $return = '';
4695
    $origin = api_get_origin();
4696
    if ($origin != 'learnpath') {
4697
        $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search"> ';
4698
        $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
4699
4700
        if (!empty($_GET['search'])) {
4701
            $return .= ': '.Security::remove_XSS($_GET['search']).' ';
4702
            $url = api_get_self().'?';
4703
            $url_parameter = [];
4704
            foreach ($_GET as $key => $value) {
4705
                if ($key != 'search') {
4706
                    $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
4707
                }
4708
            }
4709
            $url = $url.implode('&', $url_parameter);
4710
            $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('RemoveSearchResults')).'</a>';
4711
        }
4712
    }
4713
4714
    return $return;
4715
}
4716
4717
/**
4718
 * This function adds an attachment file into a forum
4719
 * @param string $file_comment  a comment about file
4720
 * @param int $last_id from forum_post table
4721
 * @return false|null
4722
 */
4723
function add_forum_attachment_file($file_comment, $last_id)
4724
{
4725
    $_course = api_get_course_info();
4726
    $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4727
4728
    if (!isset($_FILES['user_upload'])) {
4729
        return false;
4730
    }
4731
4732
    $fileCount = count($_FILES['user_upload']['name']);
4733
    $filesData = [];
4734
4735
    if (!is_array($_FILES['user_upload']['name'])) {
4736
        $filesData[] = $_FILES['user_upload'];
4737
    } else {
4738
        $fileKeys = array_keys($_FILES['user_upload']);
4739
        for ($i = 0; $i < $fileCount; $i++) {
4740
            foreach ($fileKeys as $key) {
4741
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
4742
            }
4743
        }
4744
    }
4745
4746
    foreach ($filesData as $attachment) {
4747
        if (empty($attachment['name'])) {
4748
            continue;
4749
        }
4750
4751
        $upload_ok = process_uploaded_file($attachment);
4752
4753
        if (!$upload_ok) {
4754
            continue;
4755
        }
4756
4757
        $course_dir = $_course['path'].'/upload/forum';
4758
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
4759
        $updir = $sys_course_path.$course_dir;
4760
4761
        // Try to add an extension to the file if it hasn't one.
4762
        $new_file_name = add_ext_on_mime(
4763
            stripslashes($attachment['name']),
4764
            $attachment['type']
4765
        );
4766
        // User's file name
4767
        $file_name = $attachment['name'];
4768
4769
        if (!filter_extension($new_file_name)) {
4770
            Display::addFlash(
4771
                Display::return_message(
4772
                    get_lang('UplUnableToSaveFileFilteredExtension'),
4773
                    'error'
4774
                )
4775
            );
4776
4777
            return;
4778
        }
4779
4780
        $new_file_name = uniqid('');
4781
        $new_path = $updir.'/'.$new_file_name;
4782
        $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
4783
        $safe_file_comment = Database::escape_string($file_comment);
4784
        $safe_file_name = Database::escape_string($file_name);
4785
        $safe_new_file_name = Database::escape_string($new_file_name);
4786
        $last_id = intval($last_id);
4787
        // Storing the attachments if any.
4788
        if (!$result) {
4789
            return;
4790
        }
4791
4792
        $last_id_file = Database::insert(
4793
            $agenda_forum_attachment,
4794
            [
4795
                'c_id' => api_get_course_int_id(),
4796
                'filename' => $safe_file_name,
4797
                'comment' => $safe_file_comment,
4798
                'path' => $safe_new_file_name,
4799
                'post_id' => $last_id,
4800
                'size' => intval($attachment['size']),
4801
            ]
4802
        );
4803
4804
        api_item_property_update(
4805
            $_course,
4806
            TOOL_FORUM_ATTACH,
4807
            $last_id_file,
0 ignored issues
show
Bug introduced by
It seems like $last_id_file can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4807
            /** @scrutinizer ignore-type */ $last_id_file,
Loading history...
4808
            'ForumAttachmentAdded',
4809
            api_get_user_id()
4810
        );
4811
    }
4812
}
4813
4814
/**
4815
 * This function edits an attachment file into a forum
4816
 * @param string $file_comment  a comment about file
4817
 * @param int $post_id
4818
 * @param int $id_attach attachment file Id
4819
 * @return void
4820
 */
4821
function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
4822
{
4823
    $_course = api_get_course_info();
4824
    $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4825
    $course_id = api_get_course_int_id();
4826
4827
    $fileCount = count($_FILES['user_upload']['name']);
4828
    $filesData = [];
4829
4830
    if (!is_array($_FILES['user_upload']['name'])) {
4831
        $filesData[] = $_FILES['user_upload'];
4832
    } else {
4833
        $fileKeys = array_keys($_FILES['user_upload']);
4834
4835
        for ($i = 0; $i < $fileCount; $i++) {
4836
            foreach ($fileKeys as $key) {
4837
                $filesData[$i][$key] = $_FILES['user_upload'][$key][$i];
4838
            }
4839
        }
4840
    }
4841
4842
    foreach ($filesData as $attachment) {
4843
        if (empty($attachment['name'])) {
4844
            continue;
4845
        }
4846
4847
        $upload_ok = process_uploaded_file($attachment);
4848
4849
        if (!$upload_ok) {
4850
            continue;
4851
        }
4852
4853
        $course_dir = $_course['path'].'/upload/forum';
4854
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
4855
        $updir = $sys_course_path.$course_dir;
4856
4857
        // Try to add an extension to the file if it hasn't one.
4858
        $new_file_name = add_ext_on_mime(stripslashes($attachment['name']), $attachment['type']);
4859
        // User's file name
4860
        $file_name = $attachment['name'];
4861
4862
        if (!filter_extension($new_file_name)) {
4863
            Display::addFlash(
4864
                Display::return_message(
4865
                    get_lang('UplUnableToSaveFileFilteredExtension'),
4866
                    'error'
4867
                )
4868
            );
4869
        } else {
4870
            $new_file_name = uniqid('');
4871
            $new_path = $updir.'/'.$new_file_name;
4872
            $result = @move_uploaded_file($attachment['tmp_name'], $new_path);
4873
            $safe_file_comment = Database::escape_string($file_comment);
4874
            $safe_file_name = Database::escape_string($file_name);
4875
            $safe_new_file_name = Database::escape_string($new_file_name);
4876
            $safe_post_id = (int) $post_id;
4877
            $safe_id_attach = (int) $id_attach;
4878
            // Storing the attachments if any.
4879
            if ($result) {
4880
                $sql = "UPDATE $table_forum_attachment 
4881
                        SET 
4882
                            filename = '$safe_file_name', 
4883
                            comment = '$safe_file_comment', 
4884
                            path = '$safe_new_file_name', 
4885
                            post_id = '$safe_post_id', 
4886
                            size ='".$attachment['size']."'
4887
                        WHERE c_id = $course_id AND id = '$safe_id_attach'";
4888
                Database::query($sql);
4889
                api_item_property_update(
4890
                    $_course,
4891
                    TOOL_FORUM_ATTACH,
4892
                    $safe_id_attach,
4893
                    'ForumAttachmentUpdated',
4894
                    api_get_user_id()
4895
                );
4896
            }
4897
        }
4898
    }
4899
}
4900
4901
/**
4902
 * Show a list with all the attachments according to the post's id
4903
 * @param int $post_id
4904
 * @return array with the post info
4905
 * @author Julio Montoya
4906
 * @version avril 2008, dokeos 1.8.5
4907
 */
4908
function get_attachment($post_id)
4909
{
4910
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4911
    $course_id = api_get_course_int_id();
4912
    $row = [];
4913
    $post_id = intval($post_id);
4914
    $sql = "SELECT iid, path, filename, comment 
4915
            FROM $forum_table_attachment
4916
            WHERE c_id = $course_id AND post_id = $post_id";
4917
    $result = Database::query($sql);
4918
    if (Database::num_rows($result) != 0) {
4919
        $row = Database::fetch_array($result);
4920
    }
4921
4922
    return $row;
4923
}
4924
4925
/**
4926
 * @param int $postId
4927
 *
4928
 * @return array
4929
 */
4930
function getAllAttachment($postId)
4931
{
4932
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4933
    $courseId = api_get_course_int_id();
4934
    $postId = intval($postId);
4935
    $columns = ['iid', 'path', 'filename', 'comment'];
4936
    $conditions = [
4937
        'where' => [
4938
            'c_id = ? AND post_id = ?' => [$courseId, $postId],
4939
        ],
4940
    ];
4941
    $array = Database::select(
4942
        $columns,
4943
        $forumAttachmentTable,
4944
        $conditions,
4945
        'all',
4946
        'ASSOC'
4947
    );
4948
4949
    return $array;
4950
}
4951
4952
/**
4953
 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional)
4954
 * @param int $post_id
4955
 * @param int $id_attach
4956
 * @param bool $display to show or not result message
4957
 * @return integer
4958
 * @author Julio Montoya
4959
 * @version october 2014, chamilo 1.9.8
4960
 */
4961
function delete_attachment($post_id, $id_attach = 0, $display = true)
4962
{
4963
    $_course = api_get_course_info();
4964
4965
    $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
4966
    $course_id = api_get_course_int_id();
4967
4968
    $cond = (!empty($id_attach)) ? " iid = ".(int) $id_attach."" : " post_id = ".(int) $post_id."";
4969
    $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
4970
    $res = Database::query($sql);
4971
    $row = Database::fetch_array($res);
4972
4973
    $course_dir = $_course['path'].'/upload/forum';
4974
    $sys_course_path = api_get_path(SYS_COURSE_PATH);
4975
    $updir = $sys_course_path.$course_dir;
4976
    $my_path = isset($row['path']) ? $row['path'] : null;
4977
    $file = $updir.'/'.$my_path;
4978
    if (Security::check_abs_path($file, $updir)) {
4979
        @unlink($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

4979
        /** @scrutinizer ignore-unhandled */ @unlink($file);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
4980
    }
4981
4982
    // Delete from forum_attachment table.
4983
    $sql = "DELETE FROM $forum_table_attachment 
4984
            WHERE c_id = $course_id AND $cond ";
4985
    $result = Database::query($sql);
4986
    if ($result !== false) {
4987
        $affectedRows = Database::affected_rows($result);
4988
    } else {
4989
        $affectedRows = 0;
4990
    }
4991
4992
    // Update item_property.
4993
    api_item_property_update(
4994
        $_course,
4995
        TOOL_FORUM_ATTACH,
4996
        $id_attach,
4997
        'ForumAttachmentDelete',
4998
        api_get_user_id()
4999
    );
5000
5001
    if (!empty($result) && !empty($id_attach) && $display) {
5002
        $message = get_lang('AttachmentFileDeleteSuccess');
5003
        echo Display::return_message($message, 'confirmation');
5004
    }
5005
5006
    return $affectedRows;
5007
}
5008
5009
/**
5010
 * This function gets all the forum information of the all the forum of the group
5011
 *
5012
 * @param array $groupInfo the id of the group we need the fora of (see forum.forum_of_group)
5013
 * @return array
5014
 *
5015
 * @todo this is basically the same code as the get_forums function. Consider merging the two.
5016
 */
5017
function get_forums_of_group($groupInfo)
5018
{
5019
    $table_forums = Database::get_course_table(TABLE_FORUM);
5020
    $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
5021
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5022
    $table_item_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
5023
    $course_id = api_get_course_int_id();
5024
    $groupId = (int) $groupInfo['id'];
5025
5026
    // Student
5027
    // Select all the forum information of all forums (that are visible to students).
5028
    $sql = "SELECT * FROM $table_forums forum 
5029
            INNER JOIN $table_item_property item_properties
5030
            ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5031
            WHERE
5032
                forum.forum_of_group = $groupId AND
5033
                forum.c_id = $course_id AND
5034
                item_properties.c_id = $course_id AND                
5035
                item_properties.visibility = 1 AND
5036
                item_properties.tool = '".TOOL_FORUM."'
5037
            ORDER BY forum.forum_order ASC";
5038
5039
    // Select the number of threads of the forums (only the threads that are visible).
5040
    $sql2 = "SELECT 
5041
                count(thread_id) AS number_of_threads, 
5042
                threads.forum_id
5043
            FROM $table_threads threads 
5044
            INNER JOIN $table_item_property item_properties
5045
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5046
            WHERE                
5047
                threads.c_id = $course_id AND
5048
                item_properties.c_id = $course_id AND
5049
                item_properties.visibility = 1 AND
5050
                item_properties.tool='".TOOL_FORUM_THREAD."'
5051
            GROUP BY threads.forum_id";
5052
5053
    // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
5054
    $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id
5055
            FROM $table_posts posts 
5056
            INNER JOIN $table_threads threads 
5057
            ON (posts.thread_id = threads.thread_id AND posts.c_id = threads.c_id)
5058
            INNER JOIN $table_item_property item_properties
5059
            ON (threads.thread_id = item_properties.ref AND item_properties.c_id = threads.c_id)
5060
            WHERE 
5061
                posts.visible=1 AND
5062
                posts.c_id = $course_id AND
5063
                item_properties.c_id = $course_id AND
5064
                threads.c_id = $course_id AND 
5065
                item_properties.visibility = 1 AND 
5066
                item_properties.tool='".TOOL_FORUM_THREAD."'
5067
            GROUP BY threads.forum_id";
5068
5069
    // Course Admin
5070
    if (api_is_allowed_to_edit()) {
5071
        // Select all the forum information of all forums (that are not deleted).
5072
        $sql = "SELECT *
5073
                FROM $table_forums forum 
5074
                INNER JOIN $table_item_property item_properties
5075
                ON (forum.forum_id = item_properties.ref AND item_properties.c_id = forum.c_id)
5076
                WHERE
5077
                    forum.forum_of_group = $groupId AND
5078
                    forum.c_id = $course_id AND
5079
                    item_properties.c_id = $course_id AND                    
5080
                    item_properties.visibility <> 2 AND
5081
                    item_properties.tool = '".TOOL_FORUM."'
5082
                ORDER BY forum_order ASC";
5083
5084
        // Select the number of threads of the forums (only the threads that are not deleted).
5085
        $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id
5086
                 FROM $table_threads threads 
5087
                 INNER JOIN $table_item_property item_properties
5088
                 ON (threads.thread_id=item_properties.ref AND item_properties.c_id = threads.c_id)
5089
                 WHERE
5090
                    threads.c_id = $course_id AND
5091
                    item_properties.c_id = $course_id AND
5092
                    item_properties.visibility <> 2 AND
5093
                    item_properties.tool='".TOOL_FORUM_THREAD."'
5094
                GROUP BY threads.forum_id";
5095
        // Select the number of posts of the forum.
5096
        $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id
5097
                FROM $table_posts
5098
                WHERE c_id = $course_id 
5099
                GROUP BY forum_id";
5100
    }
5101
5102
    // Handling all the forum information.
5103
    $result = Database::query($sql);
5104
    $forum_list = [];
5105
    while ($row = Database::fetch_array($result, 'ASSOC')) {
5106
        $forum_list[$row['forum_id']] = $row;
5107
    }
5108
5109
    // Handling the thread count information.
5110
    $result2 = Database::query($sql2);
5111
    while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
5112
        if (is_array($forum_list)) {
5113
            if (array_key_exists($row2['forum_id'], $forum_list)) {
5114
                $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
5115
            }
5116
        }
5117
    }
5118
5119
    // Handling the post count information.
5120
    $result3 = Database::query($sql3);
5121
    while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
5122
        if (is_array($forum_list)) {
5123
            if (array_key_exists($row3['forum_id'], $forum_list)) {
5124
                // This is needed because sql3 takes also the deleted forums into account.
5125
                $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
5126
            }
5127
        }
5128
    }
5129
5130
    // Finding the last post information
5131
    // (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
5132
    if (!empty($forum_list)) {
5133
        foreach ($forum_list as $key => $value) {
5134
            $last_post_info_of_forum = get_last_post_information($key, api_is_allowed_to_edit());
5135
            if ($last_post_info_of_forum) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $last_post_info_of_forum of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
5136
                $forum_list[$key]['last_post_id'] = $last_post_info_of_forum['last_post_id'];
5137
                $forum_list[$key]['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
5138
                $forum_list[$key]['last_post_date'] = $last_post_info_of_forum['last_post_date'];
5139
                $forum_list[$key]['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
5140
                $forum_list[$key]['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
5141
                $forum_list[$key]['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
5142
            }
5143
        }
5144
    }
5145
5146
    return $forum_list;
5147
}
5148
5149
/**
5150
 * This function stores which users have to be notified of which forums or threads
5151
 *
5152
 * @param string $content does the user want to be notified about a forum or about a thread
5153
 * @param integer $id the id of the forum or thread
5154
 * @return string language variable
5155
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5156
 * @version May 2008, dokeos 1.8.5
5157
 * @since May 2008, dokeos 1.8.5
5158
 */
5159
function set_notification($content, $id, $add_only = false)
5160
{
5161
    $_user = api_get_user_info();
5162
    // Database table definition
5163
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5164
5165
    $course_id = api_get_course_int_id();
5166
5167
    // Which database field do we have to store the id in?
5168
    if ($content == 'forum') {
5169
        $database_field = 'forum_id';
5170
    } else {
5171
        $database_field = 'thread_id';
5172
    }
5173
5174
    // First we check if the notification is already set for this.
5175
    $sql = "SELECT * FROM $table_notification
5176
            WHERE
5177
                c_id = $course_id AND
5178
                $database_field = '".Database::escape_string($id)."' AND
5179
                user_id = '".intval($_user['user_id'])."'";
5180
    $result = Database::query($sql);
5181
    $total = Database::num_rows($result);
5182
5183
    // If the user did not indicate that (s)he wanted to be notified already
5184
    // then we store the notification request (to prevent double notification requests).
5185
    if ($total <= 0) {
5186
        $sql = "INSERT INTO $table_notification (c_id, $database_field, user_id)
5187
                VALUES (".$course_id.", '".Database::escape_string($id)."','".intval($_user['user_id'])."')";
5188
        Database::query($sql);
5189
        Session::erase('forum_notification');
5190
        get_notifications_of_user(0, true);
5191
5192
        return get_lang('YouWillBeNotifiedOfNewPosts');
5193
    } else {
5194
        if (!$add_only) {
5195
            $sql = "DELETE FROM $table_notification
5196
                    WHERE
5197
                        c_id = $course_id AND
5198
                        $database_field = '".Database::escape_string($id)."' AND
5199
                        user_id = '".intval($_user['user_id'])."'";
5200
            Database::query($sql);
5201
            Session::erase('forum_notification');
5202
            get_notifications_of_user(0, true);
5203
5204
            return get_lang('YouWillNoLongerBeNotifiedOfNewPosts');
5205
        }
5206
    }
5207
}
5208
5209
/**
5210
 * This function retrieves all the email adresses of the users who wanted to be notified
5211
 * about a new post in a certain forum or thread
5212
 *
5213
 * @param string $content does the user want to be notified about a forum or about a thread
5214
 * @param integer $id the id of the forum or thread
5215
 * @return array returns
5216
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5217
 * @version May 2008, dokeos 1.8.5
5218
 * @since May 2008, dokeos 1.8.5
5219
 */
5220
function get_notifications($content, $id)
5221
{
5222
    // Database table definition
5223
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5224
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5225
    $course_id = api_get_course_int_id();
5226
5227
    // Which database field contains the notification?
5228
    if ($content == 'forum') {
5229
        $database_field = 'forum_id';
5230
    } else {
5231
        $database_field = 'thread_id';
5232
    }
5233
5234
    $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.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.user_id = notification.user_id AND
5239
                notification.$database_field= '".Database::escape_string($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 integer $forum_id the id of the forum
5256
 * @param integer $thread_id the id of the thread
5257
 * @param integer $post_id the id of the post
5258
 * @return false|null
5259
 *
5260
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5261
 * @version May 2008, dokeos 1.8.5
5262
 * @since May 2008, dokeos 1.8.5
5263
 */
5264
function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
5265
{
5266
    $_course = api_get_course_info();
5267
    $forum_id = (int) $forum_id;
5268
5269
    // The content of the mail
5270
    $thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forum_id.'&thread='.$thread_id;
5271
5272
    // Users who subscribed to the forum
5273
    if ($forum_id != 0) {
5274
        $users_to_be_notified_by_forum = get_notifications('forum', $forum_id);
5275
    } else {
5276
        return false;
5277
    }
5278
5279
    $current_thread = get_thread_information($forum_id, $thread_id);
5280
    $current_forum = get_forum_information($current_thread['forum_id']);
0 ignored issues
show
Deprecated Code introduced by
The function get_forum_information() has been deprecated: this functionality is now moved to get_forums($forum_id) ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

5280
    $current_forum = /** @scrutinizer ignore-deprecated */ get_forum_information($current_thread['forum_id']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
5281
    $subject = get_lang('NewForumPost').' - '.$_course['official_code'].' - '.$current_forum['forum_title'].' - '.$current_thread['thread_title'];
5282
5283
    // User who subscribed to the thread
5284
    if ($thread_id != 0) {
5285
        $users_to_be_notified_by_thread = get_notifications('thread', $thread_id);
5286
    }
5287
5288
    // Merging the two
5289
    $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $users_to_be_notified_by_thread does not seem to be defined for all execution paths leading up to this point.
Loading history...
5290
    $sender_id = api_get_user_id();
5291
5292
    if (is_array($users_to_be_notified)) {
5293
        foreach ($users_to_be_notified as $value) {
5294
            $user_info = api_get_user_info($value['user_id']);
5295
            $email_body = get_lang('Dear').' '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS).", <br />\n\r";
5296
            $email_body .= get_lang('NewForumPost').": ".$current_forum['forum_title'].' - '.$current_thread['thread_title']." <br />\n";
5297
            $email_body .= get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."]  <br />\n";
5298
            $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
5299
            $email_body .= get_lang('ThreadCanBeFoundHere').': <br /> <a href="'.$thread_link.'">'.$thread_link."</a>\n";
5300
5301
            MessageManager::send_message_simple(
5302
                $value['user_id'],
5303
                $subject,
5304
                $email_body,
5305
                $sender_id
5306
            );
5307
        }
5308
    }
5309
}
5310
5311
/**
5312
 * Get all the notification subscriptions of the user
5313
 * = which forums and which threads does the user wants to be informed of when a new
5314
 * post is added to this thread
5315
 *
5316
 * @param integer $user_id the user_id of a user (default = 0 => the current user)
5317
 * @param boolean $force force get the notification subscriptions (even if the information is already in the session
5318
 * @return array returns
5319
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
5320
 * @version May 2008, dokeos 1.8.5
5321
 * @since May 2008, dokeos 1.8.5
5322
 */
5323
function get_notifications_of_user($user_id = 0, $force = false)
5324
{
5325
    // Database table definition
5326
    $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
5327
    $course_id = api_get_course_int_id();
5328
    if (empty($course_id) || $course_id == -1) {
5329
        return null;
5330
    }
5331
    if ($user_id == 0) {
5332
        $user_id = api_get_user_id();
5333
    }
5334
5335
    if (!isset($_SESSION['forum_notification']) ||
5336
        $_SESSION['forum_notification']['course'] != $course_id ||
5337
        $force = true
5338
    ) {
5339
        $_SESSION['forum_notification']['course'] = $course_id;
5340
5341
        $sql = "SELECT * FROM $table_notification
5342
                WHERE c_id = $course_id AND user_id='".intval($user_id)."'";
5343
        $result = Database::query($sql);
5344
        while ($row = Database::fetch_array($result)) {
5345
            if (!is_null($row['forum_id'])) {
5346
                $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
5347
            }
5348
            if (!is_null($row['thread_id'])) {
5349
                $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
5350
            }
5351
        }
5352
    }
5353
}
5354
5355
/**
5356
 * This function counts the number of post inside a thread
5357
 * @param   int $thread_id
5358
 * @return  int the number of post inside a thread
5359
 * @author Jhon Hinojosa <[email protected]>,
5360
 * @version octubre 2008, dokeos 1.8
5361
 */
5362
function count_number_of_post_in_thread($thread_id)
5363
{
5364
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5365
    $course_id = api_get_course_int_id();
5366
    if (empty($course_id)) {
5367
        return 0;
5368
    }
5369
    $sql = "SELECT count(*) count FROM $table_posts
5370
            WHERE 
5371
                c_id = $course_id AND 
5372
                thread_id='".intval($thread_id)."' ";
5373
    $result = Database::query($sql);
5374
5375
    $count = 0;
5376
    if (Database::num_rows($result) > 0) {
5377
        $row = Database::fetch_array($result);
5378
        $count = $row['count'];
5379
    }
5380
5381
    return $count;
5382
}
5383
5384
/**
5385
 * This function counts the number of post inside a thread user
5386
 * @param   int $thread_id
5387
 * @param   int $user_id
5388
 *
5389
 * @return  int the number of post inside a thread user
5390
 */
5391
function count_number_of_post_for_user_thread($thread_id, $user_id)
5392
{
5393
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5394
    $course_id = api_get_course_int_id();
5395
    $sql = "SELECT count(iid) as count 
5396
            FROM $table_posts
5397
            WHERE c_id = $course_id AND
5398
                  thread_id=".intval($thread_id)." AND
5399
                  poster_id = ".intval($user_id)." AND visible = 1 ";
5400
    $result = Database::query($sql);
5401
    $count = 0;
5402
    if (Database::num_rows($result) > 0) {
5403
        $count = Database::fetch_array($result);
5404
        $count = $count['count'];
5405
    }
5406
5407
    return $count;
5408
}
5409
5410
/**
5411
 * This function counts the number of user register in course
5412
 * @param   int $course_id Course ID
5413
 * @deprecated use CourseManager::get_users_count_in_course
5414
 * @return  int the number of user register in course
5415
 * @author Jhon Hinojosa <[email protected]>,
5416
 * @version octubre 2008, dokeos 1.8
5417
 */
5418
function count_number_of_user_in_course($course_id)
5419
{
5420
    $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
5421
5422
    $sql = "SELECT * FROM $table
5423
            WHERE c_id ='".intval($course_id)."' ";
5424
    $result = Database::query($sql);
5425
5426
    return count(Database::store_result($result));
5427
}
5428
5429
/**
5430
 * This function retrieves information of statistical
5431
 * @param   int $thread_id
5432
 * @param   int $user_id
5433
 * @param   int $course_id
5434
 *
5435
 * @return  array the information of statistical
5436
 * @author Jhon Hinojosa <[email protected]>,
5437
 * @version oct 2008, dokeos 1.8
5438
 */
5439
function get_statistical_information($thread_id, $user_id, $course_id)
5440
{
5441
    $result = [];
5442
    $courseInfo = api_get_course_info_by_id($course_id);
5443
    $result['user_course'] = CourseManager::get_users_count_in_course($courseInfo['code']);
5444
    $result['post'] = count_number_of_post_in_thread($thread_id);
5445
    $result['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
5446
5447
    return $result;
5448
}
5449
5450
/**
5451
 * This function return the posts inside a thread from a given user
5452
 * @param   string $course_code
5453
 * @param   int $thread_id
5454
 * @param   int $user_id
5455
 *
5456
 * @return  array posts inside a thread
5457
 * @author Jhon Hinojosa <[email protected]>,
5458
 * @version oct 2008, dokeos 1.8
5459
 */
5460
function get_thread_user_post($course_code, $thread_id, $user_id)
5461
{
5462
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5463
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5464
    $thread_id = intval($thread_id);
5465
    $user_id = intval($user_id);
5466
    $course_info = api_get_user_info($course_code);
5467
    $course_id = $course_info['real_id'];
5468
5469
    if (empty($course_id)) {
5470
        $course_id = api_get_course_int_id();
5471
    }
5472
    $sql = "SELECT * FROM $table_posts posts
5473
            LEFT JOIN  $table_users users
5474
                ON posts.poster_id=users.user_id
5475
            WHERE
5476
                posts.c_id = $course_id AND
5477
                posts.thread_id='$thread_id'
5478
                AND posts.poster_id='$user_id'
5479
            ORDER BY posts.post_id ASC";
5480
5481
    $result = Database::query($sql);
5482
    $post_list = [];
5483
    while ($row = Database::fetch_array($result)) {
5484
        $row['status'] = '1';
5485
        $post_list[] = $row;
5486
        $sql = "SELECT * FROM $table_posts posts
5487
                LEFT JOIN $table_users users
5488
                ON (posts.poster_id=users.user_id)
5489
                WHERE
5490
                    posts.c_id = $course_id AND
5491
                    posts.thread_id='$thread_id'
5492
                    AND posts.post_parent_id='".$row['post_id']."'
5493
                ORDER BY posts.post_id ASC";
5494
        $result2 = Database::query($sql);
5495
        while ($row2 = Database::fetch_array($result2)) {
5496
            $row2['status'] = '0';
5497
            $post_list[] = $row2;
5498
        }
5499
    }
5500
5501
    return $post_list;
5502
}
5503
5504
/**
5505
 * This function get the name of an thread by id
5506
 * @param int thread_id
5507
 * @return String
5508
 * @author Christian Fasanando
5509
 * @author Julio Montoya <[email protected]> Adding security
5510
 */
5511
function get_name_thread_by_id($thread_id)
5512
{
5513
    $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
5514
    $course_id = api_get_course_int_id();
5515
    $sql = "SELECT thread_title 
5516
            FROM $t_forum_thread
5517
            WHERE c_id = $course_id AND thread_id = '".intval($thread_id)."' ";
5518
    $result = Database::query($sql);
5519
    $row = Database::fetch_array($result);
5520
5521
    return $row[0];
5522
}
5523
5524
/**
5525
 * This function gets all the post written by an user
5526
 * @param int $user_id
5527
 * @param string $course_code
5528
 *
5529
 * @return string
5530
 */
5531
function get_all_post_from_user($user_id, $course_code)
5532
{
5533
    $j = 0;
5534
    $forums = get_forums('', $course_code);
5535
    krsort($forums);
5536
    $forum_results = '';
5537
5538
    foreach ($forums as $forum) {
5539
        if ($forum['visibility'] == 0) {
5540
            continue;
5541
        }
5542
        if ($j <= 4) {
5543
            $threads = get_threads($forum['forum_id']);
5544
5545
            if (is_array($threads)) {
5546
                $i = 0;
5547
                $hand_forums = '';
5548
                $post_counter = 0;
5549
                foreach ($threads as $thread) {
5550
                    if ($thread['visibility'] == 0) {
5551
                        continue;
5552
                    }
5553
                    if ($i <= 4) {
5554
                        $post_list = get_thread_user_post_limit(
5555
                            $course_code,
5556
                            $thread['thread_id'],
5557
                            $user_id,
5558
                            1
5559
                        );
5560
                        $post_counter = count($post_list);
5561
                        if (is_array($post_list) && count($post_list) > 0) {
5562
                            $hand_forums .= '<div id="social-thread">';
5563
                            $hand_forums .= Display::return_icon(
5564
                                'thread.png',
5565
                                get_lang('Thread'),
5566
                                '',
5567
                                ICON_SIZE_MEDIUM
5568
                            );
5569
                            $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
5570
                            $hand_forums .= '</div>';
5571
5572
                            foreach ($post_list as $posts) {
5573
                                $hand_forums .= '<div id="social-post">';
5574
                                $hand_forums .= '<strong>'.Security::remove_XSS($posts['post_title'], STUDENT).'</strong>';
5575
                                $hand_forums .= '<br / >';
5576
                                $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
5577
                                $hand_forums .= '</div>';
5578
                                $hand_forums .= '<br / >';
5579
                            }
5580
                        }
5581
                    }
5582
                    $i++;
5583
                }
5584
                $forum_results .= '<div id="social-forum">';
5585
                $forum_results .= '<div class="clear"></div><br />';
5586
                $forum_results .= '<div id="social-forum-title">'.
5587
                    Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS($forum['forum_title'], STUDENT).
5588
                    '<div style="float:right;margin-top:-35px">
5589
                        <a href="../forum/viewforum.php?'.api_get_cidreq_params($course_code).'&forum='.$forum['forum_id'].' " >'.
5590
                            get_lang('SeeForum').'    
5591
                        </a>
5592
                     </div></div>';
5593
                $forum_results .= '<br / >';
5594
                if ($post_counter > 0) {
5595
                    $forum_results .= $hand_forums;
5596
                }
5597
                $forum_results .= '</div>';
5598
            }
5599
            $j++;
5600
        }
5601
    }
5602
5603
    return $forum_results;
5604
}
5605
5606
/**
5607
 * @param string $course_code
5608
 * @param int $thread_id
5609
 * @param int $user_id
5610
 * @param int $limit
5611
 *
5612
 * @return array
5613
 */
5614
function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
5615
{
5616
    $table_posts = Database::get_course_table(TABLE_FORUM_POST);
5617
    $table_users = Database::get_main_table(TABLE_MAIN_USER);
5618
5619
    $course_info = api_get_course_info($course_code);
5620
    $course_id = $course_info['real_id'];
5621
5622
    $sql = "SELECT * FROM $table_posts posts
5623
            LEFT JOIN  $table_users users
5624
                ON posts.poster_id=users.user_id
5625
            WHERE
5626
                posts.c_id = $course_id AND
5627
                posts.thread_id='".Database::escape_string($thread_id)."' AND 
5628
                posts.poster_id='".Database::escape_string($user_id)."'
5629
            ORDER BY posts.post_id DESC LIMIT $limit ";
5630
    $result = Database::query($sql);
5631
    $post_list = [];
5632
    while ($row = Database::fetch_array($result)) {
5633
        $row['status'] = '1';
5634
        $post_list[] = $row;
5635
    }
5636
5637
    return $post_list;
5638
}
5639
5640
/**
5641
 * @param string $user_id
5642
 * @param int $courseId
5643
 * @param int $sessionId
5644
 *
5645
 * @return array
5646
 */
5647
function getForumCreatedByUser($user_id, $courseId, $sessionId)
5648
{
5649
    $items = api_get_item_property_list_by_tool_by_user(
5650
        $user_id,
5651
        'forum',
5652
        $courseId,
5653
        $sessionId
5654
    );
5655
5656
    $courseInfo = api_get_course_info_by_id($courseId);
5657
    $forumList = [];
5658
    if (!empty($items)) {
5659
        foreach ($items as $forum) {
5660
            $forumInfo = get_forums(
5661
                $forum['ref'],
5662
                $courseInfo['code'],
5663
                true,
5664
                $sessionId
5665
            );
5666
            if (!empty($forumInfo)) {
5667
                $forumList[] = [
5668
                    $forumInfo['forum_title'],
5669
                    api_get_local_time($forum['insert_date']),
5670
                    api_get_local_time($forum['lastedit_date']),
5671
                ];
5672
            }
5673
        }
5674
    }
5675
5676
    return $forumList;
5677
}
5678
5679
/**
5680
 * This function builds an array of all the posts in a given thread
5681
 * where the key of the array is the post_id
5682
 * It also adds an element children to the array which itself is an array
5683
 * that contains all the id's of the first-level children
5684
 * @return array $rows containing all the information on the posts of a thread
5685
 * @author Patrick Cool <[email protected]>, Ghent University
5686
 */
5687
function calculate_children($rows)
5688
{
5689
    $sorted_rows = [0 => []];
5690
    if (!empty($rows)) {
5691
        foreach ($rows as $row) {
5692
            $rows_with_children[$row['post_id']] = $row;
5693
            $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
5694
        }
5695
5696
        $rows = $rows_with_children;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rows_with_children seems to be defined by a foreach iteration on line 5691. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
5697
        forumRecursiveSort($rows, $sorted_rows);
5698
        unset($sorted_rows[0]);
5699
    }
5700
5701
    return $sorted_rows;
5702
}
5703
5704
/**
5705
 * @param $rows
5706
 * @param $threads
5707
 * @param int $seed
5708
 * @param int $indent
5709
 */
5710
function forumRecursiveSort($rows, &$threads, $seed = 0, $indent = 0)
5711
{
5712
    if ($seed > 0) {
5713
        $threads[$rows[$seed]['post_id']] = $rows[$seed];
5714
        $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
5715
        $indent++;
5716
    }
5717
5718
    if (isset($rows[$seed]['children'])) {
5719
        foreach ($rows[$seed]['children'] as $child) {
5720
            forumRecursiveSort($rows, $threads, $child, $indent);
5721
        }
5722
    }
5723
}
5724
5725
/**
5726
 * Update forum attachment data, used to update comment and post ID.
5727
 * @param $array Array (field => value) to update forum attachment row.
5728
 * @param $id Attach ID to find row to update.
5729
 * @param null $courseId Course ID to find row to update.
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $courseId is correct as it would always require null to be passed?
Loading history...
5730
 * @return int Number of affected rows.
5731
 */
5732
function editAttachedFile($array, $id, $courseId = null)
5733
{
5734
    // Init variables
5735
    $setString = '';
5736
    $id = intval($id);
5737
    $courseId = intval($courseId);
5738
    if (empty($courseId)) {
5739
        // $courseId can be null, use api method
5740
        $courseId = api_get_course_int_id();
5741
    }
5742
    /*
5743
     * Check if Attachment ID and Course ID are greater than zero
5744
     * and array of field values is not empty
5745
     */
5746
    if ($id > 0 && $courseId > 0 && !empty($array) && is_array($array)) {
5747
        foreach ($array as $key => &$item) {
5748
            $item = Database::escape_string($item);
5749
            $setString .= $key.' = "'.$item.'", ';
5750
        }
5751
        // Delete last comma
5752
        $setString = substr($setString, 0, strlen($setString) - 2);
5753
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5754
        $sql = "UPDATE $forumAttachmentTable 
5755
                SET $setString WHERE c_id = $courseId AND id = $id";
5756
        $result = Database::query($sql);
5757
        if ($result !== false) {
5758
            $affectedRows = Database::affected_rows($result);
5759
            if ($affectedRows > 0) {
5760
                /*
5761
                 * If exist in $_SESSION variable, then delete them from it
5762
                 * because they would be deprecated
5763
                 */
5764
                if (!empty($_SESSION['forum']['upload_file'][$courseId][$id])) {
5765
                    unset($_SESSION['forum']['upload_file'][$courseId][$id]);
5766
                }
5767
            }
5768
5769
            return $affectedRows;
5770
        }
5771
    }
5772
5773
    return 0;
5774
}
5775
5776
/**
5777
 * Return a table where the attachments will be set
5778
 * @param int $postId Forum Post ID
5779
 *
5780
 * @return string The Forum Attachments Ajax Table
5781
 */
5782
function getAttachmentsAjaxTable($postId = 0)
5783
{
5784
    // Init variables
5785
    $postId = intval($postId);
5786
    $courseId = api_get_course_int_id();
5787
    $attachIds = getAttachmentIdsByPostId($postId, $courseId);
5788
    $fileDataContent = '';
5789
    // Update comment to show if form did not pass validation
5790
    if (!empty($_REQUEST['file_ids']) && is_array($_REQUEST['file_ids'])) {
5791
        // 'file_ids is the name from forum attachment ajax form
5792
        foreach ($_REQUEST['file_ids'] as $key => $attachId) {
5793
            if (!empty($_SESSION['forum']['upload_file'][$courseId][$attachId]) &&
5794
                is_array($_SESSION['forum']['upload_file'][$courseId][$attachId])
5795
            ) {
5796
                // If exist forum attachment then update into $_SESSION data
5797
                $_SESSION['forum']['upload_file'][$courseId][$attachId]['comment'] = $_POST['file_comments'][$key];
5798
            }
5799
        }
5800
    }
5801
5802
    // Get data to fill into attachment files table
5803
    if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
5804
        is_array($_SESSION['forum']['upload_file'][$courseId])
5805
    ) {
5806
        $uploadedFiles = $_SESSION['forum']['upload_file'][$courseId];
5807
        foreach ($uploadedFiles as $k => $uploadedFile) {
5808
            if (!empty($uploadedFile) && in_array($uploadedFile['id'], $attachIds)) {
5809
                // Buil html table including an input with attachmentID
5810
                $fileDataContent .= '<tr id="'.$uploadedFile['id'].'" ><td>'.$uploadedFile['name'].'</td><td>'.$uploadedFile['size'].'</td><td>&nbsp;'.$uploadedFile['result'].
5811
                    ' </td><td> <input style="width:90%;" type="text" value="'.$uploadedFile['comment'].'" name="file_comments[]"> </td><td>'.
5812
                    $uploadedFile['delete'].'</td>'.
5813
                    '<input type="hidden" value="'.$uploadedFile['id'].'" name="file_ids[]">'.'</tr>';
5814
            } else {
5815
                /*
5816
                 * If attachment data is empty, then delete it from $_SESSION
5817
                 * because could generate and empty row into html table
5818
                 */
5819
                unset($_SESSION['forum']['upload_file'][$courseId][$k]);
5820
            }
5821
        }
5822
    }
5823
    $style = empty($fileDataContent) ? 'display: none;' : '';
5824
    // Forum attachment Ajax table
5825
    $fileData = '
5826
    <div class="control-group " style="'. $style.'">
5827
        <label class="control-label">'.get_lang('AttachmentList').'</label>
5828
        <div class="controls">
5829
            <table id="attachmentFileList" class="files data_table span10">
5830
                <tr>
5831
                    <th>'.get_lang('FileName').'</th>
5832
                    <th>'.get_lang('Size').'</th>
5833
                    <th>'.get_lang('Status').'</th>
5834
                    <th>'.get_lang('Comment').'</th>
5835
                    <th>'.get_lang('Delete').'</th>
5836
                </tr>
5837
                '.$fileDataContent.'
5838
            </table>
5839
        </div>
5840
    </div>';
5841
5842
    return $fileData;
5843
}
5844
5845
/**
5846
 * Return an array of prepared attachment data to build forum attachment table
5847
 * Also, save this array into $_SESSION to do available the attachment data
5848
 * @param int $forumId
5849
 * @param int $threadId
5850
 * @param int $postId
5851
 * @param int $attachId
5852
 * @param int $courseId
5853
 *
5854
 * @return array
5855
 */
5856
function getAttachedFiles(
5857
    $forumId,
5858
    $threadId,
5859
    $postId = 0,
5860
    $attachId = 0,
5861
    $courseId = 0
5862
) {
5863
    $forumId = intval($forumId);
5864
    $courseId = intval($courseId);
5865
    $attachId = intval($attachId);
5866
    $postId = intval($postId);
5867
    $threadId = !empty($threadId) ? intval($threadId) : isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : '';
5868
    if (empty($courseId)) {
5869
        // $courseId can be null, use api method
5870
        $courseId = api_get_course_int_id();
5871
    }
5872
    if (empty($forumId)) {
5873
        if (!empty($_REQUEST['forum'])) {
5874
            $forumId = intval($_REQUEST['forum']);
5875
        } else {
5876
            // if forum ID is empty, cannot generate delete url
5877
5878
            return [];
5879
        }
5880
    }
5881
    // Check if exist at least one of them to filter forum attachment select query
5882
    if (empty($postId) && empty($attachId)) {
5883
        return [];
5884
    } elseif (empty($postId)) {
5885
        $filter = "AND iid = $attachId";
5886
    } elseif (empty($attachId)) {
5887
        $filter = "AND post_id = $postId";
5888
    } else {
5889
        $filter = "AND post_id = $postId AND iid = $attachId";
5890
    }
5891
    $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
5892
    $sql = "SELECT iid, comment, filename, path, size
5893
            FROM $forumAttachmentTable
5894
            WHERE c_id = $courseId $filter";
5895
    $result = Database::query($sql);
5896
    $json = [];
5897
    if ($result !== false && Database::num_rows($result) > 0) {
5898
        while ($row = Database::fetch_array($result, 'ASSOC')) {
5899
            // name contains an URL to download attachment file and its filename
5900
            $json['name'] = Display::url(
5901
                api_htmlentities($row['filename']),
5902
                api_get_path(WEB_CODE_PATH).'forum/download.php?file='.$row['path'].'&'.api_get_cidreq(),
5903
                ['target'=>'_blank', 'class' => 'attachFilename']
5904
            );
5905
            $json['id'] = $row['iid'];
5906
            $json['comment'] = $row['comment'];
5907
            // Format file size
5908
            $json['size'] = format_file_size($row['size']);
5909
            // Check if $row is consistent
5910
            if (!empty($row) && is_array($row)) {
5911
                // Set result as success and bring delete URL
5912
                $json['result'] = Display::return_icon('accept.png', get_lang('Uploaded'));
5913
                $url = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&action=delete_attach&forum='.$forumId.'&thread='.$threadId.'&id_attach='.$row['iid'];
5914
                $json['delete'] = Display::url(
5915
                    Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL),
5916
                    $url,
5917
                    ['class' => 'deleteLink']
5918
                );
5919
            } else {
5920
                // If not, set an exclamation result
5921
                $json['result'] = Display::return_icon('exclamation.png', get_lang('Error'));
5922
            }
5923
            // Store array data into $_SESSION
5924
            $_SESSION['forum']['upload_file'][$courseId][$json['id']] = $json;
5925
        }
5926
    }
5927
5928
    return $json;
5929
}
5930
5931
/**
5932
 * Clear forum attachment data stored in $_SESSION,
5933
 * If is not defined post, it will clear all forum attachment data from course
5934
 * @param int $postId -1 : Clear all attachments from course stored in $_SESSION
5935
 *                      0 : Clear attachments from course, except from temporal post "0"
5936
 *                          but without delete them from file system and database
5937
 *                     Other values : Clear attachments from course except specified post
5938
 *                          and delete them from file system and database
5939
 * @param int $courseId : Course ID, if it is null, will use api_get_course_int_id()
5940
 *
5941
 * @return array
5942
 */
5943
function clearAttachedFiles($postId = null, $courseId = null)
5944
{
5945
    // Init variables
5946
    $courseId = intval($courseId);
5947
    $postId = intval($postId);
5948
    $array = [];
5949
    if (empty($courseId)) {
5950
        // $courseId can be null, use api method
5951
        $courseId = api_get_course_int_id();
5952
    }
5953
    if ($postId === -1) {
5954
        // If post ID is -1 then delete course's attachment data from $_SESSION
5955
        if (!empty($_SESSION['forum']['upload_file'][$courseId])) {
5956
            $array = array_keys($_SESSION['forum']['upload_file'][$courseId]);
5957
            unset($_SESSION['forum']['upload_file'][$courseId]);
5958
        }
5959
    } else {
5960
        $attachIds = getAttachmentIdsByPostId($postId, $courseId);
5961
        if (!empty($_SESSION['forum']['upload_file'][$courseId]) &&
5962
            is_array($_SESSION['forum']['upload_file'][$courseId])) {
5963
            foreach ($_SESSION['forum']['upload_file'][$courseId] as $attachId => $attach) {
5964
                if (!in_array($attachId, $attachIds)) {
5965
                    // If attach ID is not into specified post, delete attachment
5966
                    // Save deleted attachment ID
5967
                    $array[] = $attachId;
5968
                    if ($postId !== 0) {
5969
                        // Post 0 is temporal, delete them from file system and DB
5970
                        delete_attachment(0, $attachId, false);
5971
                    }
5972
                    // Delete attachment data from $_SESSION
5973
                    unset($_SESSION['forum']['upload_file'][$courseId][$attachId]);
5974
                }
5975
            }
5976
        }
5977
    }
5978
5979
    return $array;
5980
}
5981
5982
/**
5983
 * Returns an array of forum attachment ids into a course and forum post
5984
 * @param int $postId
5985
 * @param int $courseId
5986
 *
5987
 * @return array
5988
 */
5989
function getAttachmentIdsByPostId($postId, $courseId = null)
5990
{
5991
    $array = [];
5992
    $courseId = intval($courseId);
5993
    $postId = intval($postId);
5994
    if (empty($courseId)) {
5995
        // $courseId can be null, use api method
5996
        $courseId = api_get_course_int_id();
5997
    }
5998
    if ($courseId > 0) {
5999
        $forumAttachmentTable = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
6000
        $sql = "SELECT id FROM $forumAttachmentTable
6001
                WHERE c_id = $courseId AND post_id = $postId";
6002
        $result = Database::query($sql);
6003
        if ($result !== false && Database::num_rows($result) > 0) {
6004
            while ($row = Database::fetch_array($result, 'ASSOC')) {
6005
                $array[] = $row['id'];
6006
            }
6007
        }
6008
    }
6009
    return $array;
6010
}
6011
6012
/**
6013
 * Check if the forum category exists looking for its title
6014
 * @param string $title The forum category title
6015
 * @param int $courseId The course ID
6016
 * @param int $sessionId Optional. The session ID
6017
 * @return boolean
6018
 */
6019
function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
6020
{
6021
    $sessionId = intval($sessionId);
6022
    $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
6023
    $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
6024
6025
    $fakeFrom = "$forumCategoryTable fc
6026
        INNER JOIN $itemProperty ip ";
6027
6028
    if ($sessionId === 0) {
6029
        $fakeFrom .= "
6030
            ON (
6031
                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)
6032
            )
6033
        ";
6034
    } else {
6035
        $fakeFrom .= "
6036
            ON (
6037
                fc.cat_id = ip.ref AND fc.c_id = ip.c_id AND fc.session_id = ip.session_id
6038
            )
6039
        ";
6040
    }
6041
6042
    $resultData = Database::select(
6043
        'fc.*',
6044
        $fakeFrom,
6045
        [
6046
            'where' => [
6047
                'ip.visibility != ? AND ' => 2,
6048
                'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
6049
                'fc.session_id = ? AND ' => $sessionId,
6050
                'fc.cat_title = ? AND ' => $title,
6051
                'fc.c_id = ?' => intval($courseId)
6052
            ]
6053
        ],
6054
        'first'
6055
    );
6056
6057
    if (empty($resultData)) {
6058
        return false;
6059
    }
6060
6061
    return $resultData;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $resultData returns the type array which is incompatible with the documented return type boolean.
Loading history...
6062
}
6063
6064
/**
6065
 * @param array $current_forum
6066
 * @param array $row
6067
 *
6068
 * @return string
6069
 */
6070
function getPostStatus($current_forum, $row, $addWrapper = true)
6071
{
6072
    $statusIcon = '';
6073
    if ($current_forum['moderated']) {
6074
        if ($addWrapper) {
6075
            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
6076
        }
6077
        $row['status'] = empty($row['status']) ? 2 : $row['status'];
6078
6079
        $addUrl = false;
6080
        $showStatus = false;
6081
        if (api_is_allowed_to_edit(false, true)) {
6082
            $addUrl = true;
6083
        } else {
6084
            if ($row['user_id'] == api_get_user_id()) {
6085
                $showStatus = true;
6086
            }
6087
        }
6088
6089
        $label = '';
6090
        $icon = '';
6091
        $buttonType = '';
6092
        switch ($row['status']) {
6093
            case CForumPost::STATUS_VALIDATED:
6094
                $label = get_lang('Validated');
6095
                $icon = 'check-circle';
6096
                $buttonType = 'success';
6097
                break;
6098
            case CForumPost::STATUS_WAITING_MODERATION:
6099
                $label = get_lang('WaitingModeration');
6100
                $icon = 'warning';
6101
                $buttonType = 'warning';
6102
                break;
6103
            case CForumPost::STATUS_REJECTED:
6104
                $label = get_lang('Rejected');
6105
                $icon = 'minus-circle';
6106
                $buttonType = 'danger';
6107
                break;
6108
        }
6109
6110
        if ($addUrl) {
6111
            $statusIcon .= Display::toolbarButton(
6112
                $label.'&nbsp;',
6113
                'javascript:void(0)',
6114
                $icon,
6115
                $buttonType,
6116
                ['class' => 'change_post_status']
6117
            );
6118
        } else {
6119
            if ($showStatus) {
6120
                $statusIcon .= Display::label(
6121
                    Display::returnFontAwesomeIcon($icon).$label,
6122
                    $buttonType
6123
                );
6124
            }
6125
        }
6126
6127
        if ($addWrapper) {
6128
            $statusIcon .= '</span>';
6129
        }
6130
    }
6131
6132
    return $statusIcon;
6133
}
6134
6135
/**
6136
 * @param array $forumInfo
6137
 * @param int $threadId
6138
 * @param int $status
6139
 * @return mixed
6140
 */
6141
function getCountPostsWithStatus($status, $forumInfo, $threadId = null)
6142
{
6143
    $em = Database::getManager();
6144
    $criteria = Criteria::create();
6145
    $criteria
6146
        ->where(Criteria::expr()->eq('status', $status))
6147
        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
6148
        ->andWhere(Criteria::expr()->eq('visible', 1))
6149
    ;
6150
6151
    if (!empty($threadId)) {
6152
        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
6153
    }
6154
6155
    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
6156
    $qb->select('count(p.iid)')
6157
        ->addCriteria($criteria);
6158
6159
    return $qb->getQuery()->getSingleScalarResult();
6160
}
6161
6162
/**
6163
 * @param array $forum
6164
 * @param array $post
6165
 *
6166
 * @return bool
6167
 */
6168
function postIsEditableByStudent($forum, $post)
6169
{
6170
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
6171
        return true;
6172
    }
6173
6174
    if ($forum['moderated'] == 1) {
6175
        if (is_null($post['status'])) {
6176
            return true;
6177
        } else {
6178
            return in_array(
6179
                $post['status'],
6180
                [
6181
                    CForumPost::STATUS_WAITING_MODERATION,
6182
                    CForumPost::STATUS_REJECTED,
6183
                ]
6184
            );
6185
        }
6186
    } else {
6187
        return true;
6188
    }
6189
}
6190