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

store_add_dropbox()   F

Complexity

Conditions 44
Paths 693

Size

Total Lines 250
Code Lines 158

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 44
eloc 158
nc 693
nop 2
dl 0
loc 250
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
6
/**
7
* This file contains additional dropbox functions. Initially there were some
8
* functions in the init files also but I have moved them over
9
* to one file -- Patrick Cool <[email protected]>, Ghent University
10
* @author Julio Montoya adding c_id support
11
*/
12
13
$this_section = SECTION_COURSES;
14
15
$htmlHeadXtra[] = '<script>
16
function setFocus(){
17
    $("#category_title").focus();
18
}
19
$(document).ready(function () {
20
    setFocus();
21
});
22
</script>';
23
24
/**
25
* This function is a wrapper function for the multiple actions feature.
26
* @return   string|null   If there is a problem, return a string message, otherwise nothing
27
* @author   Patrick Cool <[email protected]>, Ghent University
28
* @version  march 2006
29
*/
30
function handle_multiple_actions()
31
{
32
    $_user = api_get_user_info();
33
    $is_courseAdmin = api_is_course_admin();
34
    $is_courseTutor = api_is_course_tutor();
35
36
    // STEP 1: are we performing the actions on the received or on the sent files?
37
    if ($_POST['action'] == 'delete_received' || $_POST['action'] == 'download_received') {
38
        $part = 'received';
39
    } elseif ($_POST['action'] == 'delete_sent' || $_POST['action'] == 'download_sent') {
40
        $part = 'sent';
41
    }
42
43
    // STEP 2: at least one file has to be selected. If not we return an error message
44
    $ids = isset($_GET['id']) ? $_GET['id'] : [];
45
    if (count($ids) > 0) {
46
        $checked_file_ids = $_POST['id'];
47
    } else {
48
        foreach ($_POST as $key => $value) {
49
            if (strstr($value, $part.'_') && $key != 'view_received_category' && $key != 'view_sent_category') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $part does not seem to be defined for all execution paths leading up to this point.
Loading history...
50
                $checked_files = true;
51
                $checked_file_ids[] = intval(substr($value, strrpos($value, '_')));
52
            }
53
        }
54
    }
55
    $checked_file_ids = $_POST['id'];
56
57
    if (!is_array($checked_file_ids) || count($checked_file_ids) == 0) {
58
        return get_lang('CheckAtLeastOneFile');
59
    }
60
61
    // STEP 3A: deleting
62
    if ($_POST['action'] == 'delete_received' || $_POST['action'] == 'delete_sent') {
63
        $dropboxfile = new Dropbox_Person($_user['user_id'], $is_courseAdmin, $is_courseTutor);
64
        foreach ($checked_file_ids as $key => $value) {
65
            if ($_GET['view'] == 'received') {
66
                $dropboxfile->deleteReceivedWork($value);
67
                $message = get_lang('ReceivedFileDeleted');
68
            }
69
            if ($_GET['view'] == 'sent' || empty($_GET['view'])) {
70
                $dropboxfile->deleteSentWork($value);
71
                $message = get_lang('SentFileDeleted');
72
            }
73
        }
74
        return $message;
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...
75
    }
76
77
    // STEP 3B: giving comment
78
    if ($_POST['actions'] == 'comment') {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
79
        // This has not been implemented.
80
        // The idea was that it would be possible to write the same feedback for the selected documents.
81
    }
82
83
    // STEP 3C: moving
84
    if (strstr($_POST['action'], 'move_')) {
85
        // check move_received_n or move_sent_n command
86
        if (strstr($_POST['action'], 'received')) {
87
            $part = 'received';
88
            $to_cat_id = str_replace('move_received_', '', $_POST['action']);
89
        } else {
90
            $part = 'sent';
91
            $to_cat_id = str_replace('move_sent_', '', $_POST['action']);
92
        }
93
94
        foreach ($checked_file_ids as $value) {
95
            store_move($value, $to_cat_id, $part);
96
        }
97
98
        return get_lang('FilesMoved');
99
    }
100
101
    // STEP 3D: downloading
102
    if ($_POST['action'] == 'download_sent' || $_POST['action'] == 'download_received') {
103
        zip_download($checked_file_ids);
104
    }
105
}
106
107
/**
108
 * Get conf settings
109
 * @return array
110
 */
111
function getDropboxConf()
112
{
113
    return Session::read('dropbox_conf');
114
}
115
116
/**
117
* This function deletes a dropbox category
118
*
119
* @todo give the user the possibility what needs to be done with the files
120
 * in this category: move them to the root, download them as a zip, delete them
121
*
122
* @author Patrick Cool <[email protected]>, Ghent University
123
* @version march 2006
124
*/
125
function delete_category($action, $id, $user_id = null)
126
{
127
    $course_id = api_get_course_int_id();
128
    $is_courseAdmin = api_is_course_admin();
129
    $is_courseTutor = api_is_course_tutor();
130
131
    if (empty($user_id)) {
132
        $user_id = api_get_user_id();
133
    }
134
135
    $cat = get_dropbox_category($id);
136
    if (count($cat) == 0) {
137
        return false;
138
    }
139
140
    if ($cat['user_id'] != $user_id && !api_is_platform_admin($user_id)) {
0 ignored issues
show
Bug introduced by
It seems like $user_id can also be of type integer; however, parameter $allowSessionAdmins of api_is_platform_admin() 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

140
    if ($cat['user_id'] != $user_id && !api_is_platform_admin(/** @scrutinizer ignore-type */ $user_id)) {
Loading history...
141
        return false;
142
    }
143
144
    // an additional check that might not be necessary
145
    if ($action == 'deletereceivedcategory') {
146
        $sentreceived = 'received';
147
        $entries_table = Database::get_course_table(TABLE_DROPBOX_POST);
148
        $id_field = 'file_id';
149
        $return_message = get_lang('ReceivedCatgoryDeleted');
150
    } elseif ($action == 'deletesentcategory') {
151
        $sentreceived = 'sent';
152
        $entries_table = Database::get_course_table(TABLE_DROPBOX_FILE);
153
        $id_field = 'id';
154
        $return_message = get_lang('SentCatgoryDeleted');
155
    } else {
156
        return get_lang('Error');
157
    }
158
159
    // step 1: delete the category
160
    $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_CATEGORY)."
161
            WHERE c_id = $course_id AND cat_id='".intval($id)."' AND $sentreceived='1'";
162
    Database::query($sql);
163
164
    // step 2: delete all the documents in this category
165
    $sql = "SELECT * FROM ".$entries_table."
166
            WHERE c_id = $course_id AND cat_id='".intval($id)."'";
167
    $result = Database::query($sql);
168
169
    while ($row = Database::fetch_array($result)) {
170
        $dropboxfile = new Dropbox_Person($user_id, $is_courseAdmin, $is_courseTutor);
171
        if ($action == 'deletereceivedcategory') {
172
            $dropboxfile->deleteReceivedWork($row[$id_field]);
173
        }
174
        if ($action == 'deletesentcategory') {
175
            $dropboxfile->deleteSentWork($row[$id_field]);
176
        }
177
    }
178
179
    return $return_message;
180
}
181
182
/**
183
* Displays the form to move one individual file to a category
184
*@ return html code of the form that appears in a message box.
185
* @author Julio Montoya - function rewritten
186
*/
187
function display_move_form(
188
    $part,
189
    $id,
190
    $target = [],
191
    $extra_params = [],
192
    $viewReceivedCategory,
193
    $viewSentCategory,
194
    $view
195
) {
196
    $form = new FormValidator(
197
        'form1',
198
        'post',
199
        api_get_self().'?view_received_category='.$viewReceivedCategory.'&view_sent_category='.$viewSentCategory.'&view='.$view.'&'.$extra_params
200
    );
201
    $form->addElement('header', get_lang('MoveFileTo'));
202
    $form->addElement('hidden', 'id', intval($id));
203
    $form->addElement('hidden', 'part', Security::remove_XSS($part));
204
205
    $options = ['0' => get_lang('Root')];
206
    foreach ($target as $category) {
207
        $options[$category['cat_id']] = $category['cat_name'];
208
    }
209
    $form->addElement('select', 'move_target', get_lang('MoveFileTo'), $options);
210
    $form->addButtonMove(get_lang('MoveFile'), 'do_move');
211
    $form->display();
212
}
213
214
/**
215
* This function moves a file to a different category
216
*
217
* @param int $id the id of the file we are moving
218
* @param int $target the id of the folder we are moving to
219
* @param string $part are we moving a received file or a sent file?
220
*
221
* @return string string
222
*
223
* @author Patrick Cool <[email protected]>, Ghent University
224
* @version march 2006
225
*/
226
function store_move($id, $target, $part)
227
{
228
    $_user = api_get_user_info();
229
    $course_id = api_get_course_int_id();
230
231
    if ((isset($id) && $id != '') &&
232
        (isset($target) && $target != '') &&
233
        (isset($part) && $part != '')
234
    ) {
235
        if ($part == 'received') {
236
            $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_POST)."
237
                    SET cat_id = ".intval($target)."
238
                    WHERE c_id = $course_id AND dest_user_id = ".intval($_user['user_id'])."
239
                    AND file_id = ".intval($id)."";
240
            Database::query($sql);
241
            $return_message = get_lang('ReceivedFileMoved');
242
        }
243
        if ($part == 'sent') {
244
            $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FILE)."
245
                    SET cat_id = ".intval($target)."
246
                    WHERE
247
                        c_id = $course_id AND
248
                        uploader_id = ".intval($_user['user_id'])." AND
249
                        id = ".intval($id);
250
            Database::query($sql);
251
            $return_message = get_lang('SentFileMoved');
252
        }
253
    } else {
254
        $return_message = get_lang('NotMovedError');
255
    }
256
257
    return $return_message;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $return_message does not seem to be defined for all execution paths leading up to this point.
Loading history...
258
}
259
260
/**
261
* This function retrieves all dropbox categories and returns them as an array
262
*
263
* @param $filter default '', when we need only the categories of the sent or the received part.
264
*
265
* @return array
266
*
267
* @author Patrick Cool <[email protected]>, Ghent University
268
* @version march 2006
269
*/
270
function get_dropbox_categories($filter = '')
271
{
272
    $course_id = api_get_course_int_id();
273
    $_user = api_get_user_info();
274
    $return_array = [];
275
276
    $session_id = api_get_session_id();
277
    $condition_session = api_get_session_condition($session_id);
278
279
    $sql = "SELECT * FROM ".Database::get_course_table(TABLE_DROPBOX_CATEGORY)."
280
            WHERE c_id = $course_id AND user_id='".$_user['user_id']."' $condition_session";
281
282
    $result = Database::query($sql);
283
    while ($row = Database::fetch_array($result)) {
284
        if (($filter == 'sent' && $row['sent'] == 1) || ($filter == 'received' && $row['received'] == 1) || $filter == '') {
285
            $return_array[$row['cat_id']] = $row;
286
        }
287
    }
288
289
    return $return_array;
290
}
291
292
/**
293
 * Get a dropbox category details
294
 * @param int The category ID
295
 * @return array The details of this category
296
 */
297
function get_dropbox_category($id)
298
{
299
    $course_id = api_get_course_int_id();
300
    if (empty($id) or $id != intval($id)) {
301
        return [];
302
    }
303
    $sql = "SELECT * FROM ".Database::get_course_table(TABLE_DROPBOX_CATEGORY)."
304
            WHERE c_id = $course_id AND cat_id='".$id."'";
305
    $res = Database::query($sql);
306
    if ($res === false) {
307
        return [];
308
    }
309
    $row = Database::fetch_assoc($res);
310
    return $row;
311
}
312
313
/**
314
 * This functions stores a new dropboxcategory
315
 *
316
 * @var  it might not seem very elegant if you create a category in sent
317
 * and in received with the same name that you get two entries in the
318
 *       dropbox_category table but it is the easiest solution. You get
319
 *       cat_name | received | sent | user_id
320
 *       test     |    1     |   0  |    237
321
 *       test     |    0     |   1  |    237
322
 *       more elegant would be
323
 *       test     |    1     |   1  |    237
324
 *
325
 * @author Patrick Cool <[email protected]>, Ghent University
326
 * @version march 2006
327
 */
328
function store_addcategory()
329
{
330
    $course_id = api_get_course_int_id();
331
    $_user = api_get_user_info();
332
333
    // check if the target is valid
334
    if ($_POST['target'] == 'sent') {
335
        $sent = 1;
336
        $received = 0;
337
    } elseif ($_POST['target'] == 'received') {
338
        $sent = 0;
339
        $received = 1;
340
    } else {
341
        return get_lang('Error');
342
    }
343
344
    // check if the category name is valid
345
    if ($_POST['category_name'] == '') {
346
        return ['type' => 'error', 'message' => get_lang('ErrorPleaseGiveCategoryName')];
347
    }
348
349
    if (!isset($_POST['edit_id'])) {
350
        $session_id = api_get_session_id();
351
        // step 3a, we check if the category doesn't already exist
352
        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_DROPBOX_CATEGORY)."
353
                WHERE
354
                    c_id = $course_id AND
355
                    user_id='".$_user['user_id']."' AND
356
                    cat_name='".Database::escape_string($_POST['category_name'])."' AND
357
                    received='".$received."' AND
358
                    sent='$sent' AND
359
                    session_id='$session_id'";
360
        $result = Database::query($sql);
361
362
        // step 3b, we add the category if it does not exist yet.
363
        if (Database::num_rows($result) == 0) {
364
            $params = [
365
                'cat_id' => 0,
366
                'c_id' => $course_id,
367
                'cat_name' => $_POST['category_name'],
368
                'received' => $received,
369
                'sent' => $sent,
370
                'user_id' => $_user['user_id'],
371
                'session_id' => $session_id,
372
            ];
373
            $id = Database::insert(Database::get_course_table(TABLE_DROPBOX_CATEGORY), $params);
374
            if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $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...
375
                $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_CATEGORY)." SET cat_id = iid WHERE iid = $id";
376
                Database::query($sql);
377
            }
378
379
            return ['type' => 'confirmation', 'message' => get_lang('CategoryStored')];
380
        } else {
381
            return ['type' => 'error', 'message' => get_lang('CategoryAlreadyExistsEditIt')];
382
        }
383
    } else {
384
        $params = [
385
            'cat_name' => $_POST['category_name'],
386
            'received' => $received,
387
            'sent' => $sent
388
        ];
389
390
        Database::update(
391
            Database::get_course_table(TABLE_DROPBOX_CATEGORY),
392
            $params,
393
            [
394
                'c_id = ? AND user_id = ? AND cat_id = ?' => [
395
                    $course_id,
396
                    $_user['user_id'],
397
                    $_POST['edit_id'],
398
                ],
399
            ]
400
        );
401
402
        return ['type' => 'confirmation', 'message' => get_lang('CategoryModified')];
403
    }
404
}
405
406
/**
407
* This function displays the form to add a new category.
408
*
409
* @param $category_name this parameter is the name of the category (used when no section is selected)
410
* @param $id this is the id of the category we are editing.
411
*
412
* @author Patrick Cool <[email protected]>, Ghent University
413
  @author Julio Montoya UI changes
414
 *
415
* @version march 2006
416
*/
0 ignored issues
show
Documentation Bug introduced by
The doc comment this at position 0 could not be parsed: 'this' is only available from within classes.
Loading history...
417
function display_addcategory_form($category_name = '', $id = '', $action)
418
{
419
    $course_id = api_get_course_int_id();
420
    $title = get_lang('AddNewCategory');
421
422
    if (isset($id) && $id != '') {
423
        // retrieve the category we are editing
424
        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_DROPBOX_CATEGORY)."
425
                WHERE c_id = $course_id AND cat_id = ".intval($id);
426
        $result = Database::query($sql);
427
        $row = Database::fetch_array($result);
428
429
        if (empty($category_name)) {
430
            // after an edit with an error we do not want to return to the
431
            // original name but the name we already modified.
432
            // (happens when createinrecievedfiles AND createinsentfiles are not checked)
433
            $category_name = $row['cat_name'];
434
        }
435
        if ($row['received'] == '1') {
436
            $target = 'received';
437
        }
438
        if ($row['sent'] == '1') {
439
            $target = 'sent';
440
        }
441
        $title = get_lang('EditCategory');
442
    }
443
444
    if ($action == 'addreceivedcategory') {
445
        $target = 'received';
446
    }
447
    if ($action == 'addsentcategory') {
448
        $target = 'sent';
449
    }
450
451
    if ($action == 'editcategory') {
452
        $text = get_lang('ModifyCategory');
453
    } elseif ($action == 'addreceivedcategory' || $action == 'addsentcategory') {
454
        $text = get_lang('CreateCategory');
455
    }
456
457
    $form = new FormValidator(
458
        'add_new_category',
459
        'post',
460
        api_get_self().'?'.api_get_cidreq().'&view='.Security::remove_XSS($_GET['view'])
461
    );
462
    $form->addElement('header', $title);
463
464
    if (isset($id) && $id != '') {
465
        $form->addElement('hidden', 'edit_id', intval($id));
466
    }
467
    $form->addElement('hidden', 'action', Security::remove_XSS($action));
468
    $form->addElement('hidden', 'target', Security::remove_XSS($target));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $target does not seem to be defined for all execution paths leading up to this point.
Loading history...
469
470
    $form->addElement('text', 'category_name', get_lang('CategoryName'));
471
    $form->addRule('category_name', get_lang('ThisFieldIsRequired'), 'required');
472
    $form->addButtonSave($text, 'StoreCategory');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $text does not seem to be defined for all execution paths leading up to this point.
Loading history...
473
474
    $defaults = [];
475
    $defaults['category_name'] = $category_name;
476
    $form->setDefaults($defaults);
477
    $form->display();
478
}
479
480
/**
481
 * this function displays the form to upload a new item to the dropbox.
482
 *
483
 * @param $viewReceivedCategory
484
 * @param $viewSentCategory
485
 * @param $view
486
 * @param int $id
487
 * @author Patrick Cool <[email protected]>, Ghent University
488
 * @author Julio Montoya
489
 * @version march 2006
490
 */
491
function display_add_form($viewReceivedCategory, $viewSentCategory, $view, $id = 0)
492
{
493
    $course_info = api_get_course_info();
494
    $_user = api_get_user_info();
495
    $is_courseAdmin = api_is_course_admin();
496
    $is_courseTutor = api_is_course_tutor();
497
    $origin = api_get_origin();
498
499
    $token = Security::get_token();
500
    $dropbox_person = new Dropbox_Person(
501
        api_get_user_id(),
502
        $is_courseAdmin,
503
        $is_courseTutor
504
    );
505
506
    $idCondition = !empty($id) ? '&id='.(int) $id : '';
507
508
    $url = api_get_self().'?view_received_category='.$viewReceivedCategory.'&view_sent_category='.$viewSentCategory.'&view='.$view.'&'.api_get_cidreq().$idCondition;
509
    $form = new FormValidator(
510
        'sent_form',
511
        'post',
512
        $url,
513
        null,
514
        [
515
            'enctype' => 'multipart/form-data',
516
            'onsubmit' => 'javascript: return checkForm(this);',
517
        ]
518
    );
519
520
    $form->addElement('header', get_lang('UploadNewFile'));
521
    $maxFileSize = api_get_setting('dropbox_max_filesize');
522
    $form->addElement('hidden', 'MAX_FILE_SIZE', $maxFileSize);
523
    $form->addElement('hidden', 'sec_token', $token);
524
    $form->addElement('hidden', 'origin', $origin);
525
    $form->addElement(
526
        'file',
527
        'file',
528
        get_lang('UploadFile'),
529
        ['onChange' => 'javascript: checkfile(this.value);']
530
    );
531
532
    $allowOverwrite = api_get_setting('dropbox_allow_overwrite');
533
    if ($allowOverwrite == 'true' && empty($idCondition)) {
534
        $form->addElement(
535
            'checkbox',
536
            'cb_overwrite',
537
            null,
538
            get_lang('OverwriteFile'),
539
            ['id' => 'cb_overwrite']
540
        );
541
    }
542
543
    // List of all users in this course and all virtual courses combined with it
544
    if (api_get_session_id()) {
545
        $complete_user_list_for_dropbox = [];
546
        if (api_get_setting('dropbox_allow_student_to_student') == 'true' || $_user['status'] != STUDENT) {
547
            $complete_user_list_for_dropbox = CourseManager:: get_user_list_from_course_code(
548
                $course_info['code'],
549
                api_get_session_id(),
550
                null,
551
                null,
552
                0
553
            );
554
        }
555
556
        $complete_user_list2 = CourseManager::get_coach_list_from_course_code(
557
            $course_info['code'],
558
            api_get_session_id()
559
        );
560
561
        $generalCoachList = [];
562
        $courseCoachList = [];
563
        foreach ($complete_user_list2 as $coach) {
564
            if ($coach['type'] == 'general_coach') {
565
                $generalCoachList[] = $coach;
566
            } else {
567
                $courseCoachList[] = $coach;
568
            }
569
        }
570
571
        $hideCourseCoach = api_get_setting('dropbox_hide_course_coach');
572
        if ($hideCourseCoach == 'false') {
573
            $complete_user_list_for_dropbox = array_merge(
574
                $complete_user_list_for_dropbox,
0 ignored issues
show
Bug introduced by
It seems like $complete_user_list_for_dropbox can also be of type integer; however, parameter $array1 of array_merge() does only seem to accept array, 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

574
                /** @scrutinizer ignore-type */ $complete_user_list_for_dropbox,
Loading history...
575
                $courseCoachList
576
            );
577
        }
578
        $hideGeneralCoach = api_get_setting('dropbox_hide_general_coach');
579
580
        if ($hideGeneralCoach == 'false') {
581
            $complete_user_list_for_dropbox = array_merge(
582
                $complete_user_list_for_dropbox,
583
                $generalCoachList
584
            );
585
        }
586
    } else {
587
        if (api_get_setting('dropbox_allow_student_to_student') == 'true' || $_user['status'] != STUDENT) {
588
            $complete_user_list_for_dropbox = CourseManager::get_user_list_from_course_code(
589
                $course_info['code'],
590
                api_get_session_id()
591
            );
592
        } else {
593
            $complete_user_list_for_dropbox = CourseManager::get_teacher_list_from_course_code(
594
                $course_info['code'],
595
                false
596
            );
597
        }
598
    }
599
600
    if (!empty($complete_user_list_for_dropbox)) {
601
        foreach ($complete_user_list_for_dropbox as $k => $e) {
602
            $complete_user_list_for_dropbox[$k] = $e + [
603
                'lastcommafirst' => api_get_person_name(
604
                    $e['firstname'],
605
                    $e['lastname']
606
                ),
607
            ];
608
        }
609
        $complete_user_list_for_dropbox = TableSort::sort_table($complete_user_list_for_dropbox, 'lastcommafirst');
0 ignored issues
show
Bug introduced by
It seems like $complete_user_list_for_dropbox can also be of type integer; however, parameter $data of TableSort::sort_table() does only seem to accept array, 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

609
        $complete_user_list_for_dropbox = TableSort::sort_table(/** @scrutinizer ignore-type */ $complete_user_list_for_dropbox, 'lastcommafirst');
Loading history...
610
    }
611
612
    /*
613
        Create the options inside the select box:
614
        List all selected users their user id as value and a name string as display
615
    */
616
    $current_user_id = '';
617
    $allowStudentToStudent = api_get_setting('dropbox_allow_student_to_student');
618
    $options = [];
619
    $userGroup = new UserGroup();
620
    foreach ($complete_user_list_for_dropbox as $current_user) {
621
        if ((
622
            $dropbox_person -> isCourseTutor
623
                || $dropbox_person -> isCourseAdmin
624
                || $allowStudentToStudent == 'true'
625
                || $current_user['status'] != 5                         // Always allow teachers.
626
                || $current_user['is_tutor'] == 1                       // Always allow tutors.
627
                ) && $current_user['user_id'] != $_user['user_id']) {   // Don't include yourself.
628
            if ($current_user['user_id'] == $current_user_id) {
629
                continue;
630
            }
631
            $userId = $current_user['user_id'];
632
            $userInfo = api_get_user_info($userId);
633
            if ($userInfo['status'] != INVITEE) {
634
                $groupNameListToString = '';
635
                if (!empty($groups)) {
636
                    $groupNameList = array_column($groups, 'name');
637
                    $groupNameListToString = ' - ['.implode(', ', $groupNameList).']';
638
                }
639
                $groups = $userGroup->getUserGroupListByUser($userId);
640
641
                $full_name = $userInfo['complete_name'].$groupNameListToString;
642
                $current_user_id = $current_user['user_id'];
643
                $options['user_'.$current_user_id] = $full_name;
644
            }
645
        }
646
    }
647
648
    /*
649
    * Show groups
650
    */
651
    $allowGroups = api_get_setting('dropbox_allow_group');
652
    if (($dropbox_person->isCourseTutor || $dropbox_person->isCourseAdmin)
653
        && $allowGroups == 'true' || $allowStudentToStudent == 'true'
654
    ) {
655
        $complete_group_list_for_dropbox = GroupManager::get_group_list(null, $course_info);
656
657
        if (count($complete_group_list_for_dropbox) > 0) {
658
            foreach ($complete_group_list_for_dropbox as $current_group) {
659
                if ($current_group['number_of_members'] > 0) {
660
                    $options['group_'.$current_group['id']] = 'G: '.$current_group['name'].' - '.$current_group['number_of_members'].' '.get_lang('Users');
661
                }
662
            }
663
        }
664
    }
665
666
    $allowUpload = api_get_setting('dropbox_allow_just_upload');
667
    if ($allowUpload == 'true') {
668
        $options['user_'.$_user['user_id']] = get_lang('JustUploadInSelect');
669
    }
670
671
    if (empty($idCondition)) {
672
        $form->addSelect(
673
            'recipients',
674
            get_lang('SendTo'),
675
            $options,
676
            [
677
                'multiple' => 'multiple',
678
                'size' => '10'
679
            ]
680
        );
681
    }
682
    $form->addButtonUpload(get_lang('Upload'), 'submitWork');
683
684
    $headers = [
685
        get_lang('Upload'),
686
        get_lang('Upload').' ('.get_lang('Simple').')',
687
    ];
688
689
    $multipleForm = new FormValidator(
690
        'sent_multiple',
691
        'post',
692
        '#',
693
        null,
694
        ['enctype' => 'multipart/form-data', 'id' => 'fileupload']
695
    );
696
697
    if (empty($idCondition)) {
698
        $multipleForm->addSelect(
699
            'recipients',
700
            get_lang('SendTo'),
701
            $options,
702
            [
703
                'multiple' => 'multiple',
704
                'size' => '10',
705
                'id' => 'recipient_form'
706
            ]
707
        );
708
    }
709
710
    $url = api_get_path(WEB_AJAX_PATH).'dropbox.ajax.php?'.api_get_cidreq().'&a=upload_file&'.$idCondition;
711
    if (empty($idCondition)) {
712
        $multipleForm->addHtml('<div id="multiple_form" style="display:none">');
713
    }
714
    $multipleForm->addMultipleUpload($url);
715
    if (empty($idCondition)) {
716
        $multipleForm->addHtml('</div>');
717
    }
718
719
    echo Display::tabs(
720
        $headers,
721
        [$multipleForm->returnForm(), $form->returnForm()],
722
        'tabs'
723
    );
724
}
725
726
/**
727
* @param string $user_id
728
* @return boolean indicating if user with user_id=$user_id is a course member
729
* @todo check if this function is still necessary. There might be a library function for this.
730
*/
731
function isCourseMember($user_id)
732
{
733
    $_course = api_get_course_info();
734
    $course_code = $_course['code'];
735
    $is_course_member = CourseManager::is_user_subscribed_in_course($user_id, $course_code, true);
736
737
    return $is_course_member;
738
}
739
740
/**
741
* Checks if there are files in the dropbox_file table that aren't used anymore in dropbox_person table.
742
* If there are, all entries concerning the file are deleted from the db + the file is deleted from the server
743
*/
744
function removeUnusedFiles()
745
{
746
    $_course = api_get_course_info();
747
    $course_id = $_course['real_id'];
748
749
    // select all files that aren't referenced anymore
750
    $sql = "SELECT DISTINCT f.id, f.filename
751
            FROM " . Database::get_course_table(TABLE_DROPBOX_FILE)." f
752
            LEFT JOIN " . Database::get_course_table(TABLE_DROPBOX_PERSON)." p
753
            ON (f.id = p.file_id)
754
            WHERE p.user_id IS NULL AND
755
                  f.c_id = $course_id
756
            ";
757
    $result = Database::query($sql);
758
    while ($res = Database::fetch_array($result)) {
759
        //delete the selected files from the post and file tables
760
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_POST)."
761
                WHERE c_id = $course_id AND file_id = '".$res['id']."'";
762
        Database::query($sql);
763
        $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_FILE)."
764
                WHERE c_id = $course_id AND id ='".$res['id']."'";
765
        Database::query($sql);
766
        //delete file from server
767
        @unlink(api_get_path(SYS_COURSE_PATH).$_course['path'].'/dropbox/'.$res['filename']);
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

767
        /** @scrutinizer ignore-unhandled */ @unlink(api_get_path(SYS_COURSE_PATH).$_course['path'].'/dropbox/'.$res['filename']);

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...
768
    }
769
}
770
771
/**
772
*
773
* Mailing zip-file is posted to (dest_user_id = ) mailing pseudo_id
774
* and is only visible to its uploader (user_id).
775
*
776
* Mailing content files have uploader_id == mailing pseudo_id, a normal recipient,
777
* and are visible initially to recipient and pseudo_id.
778
*
779
* @author René Haentjens, Ghent University
780
*
781
* @todo check if this function is still necessary.
782
*/
783
function getUserOwningThisMailing($mailingPseudoId, $owner = 0, $or_die = '')
784
{
785
    $course_id = api_get_course_int_id();
786
787
    $mailingPseudoId = intval($mailingPseudoId);
788
    $sql = "SELECT f.uploader_id
789
            FROM " . Database::get_course_table(TABLE_DROPBOX_FILE)." f
790
            LEFT JOIN " . Database::get_course_table(TABLE_DROPBOX_POST)." p
791
            ON (f.id = p.file_id AND f.c_id = $course_id AND p.c_id = $course_id)
792
            WHERE
793
                p.dest_user_id = '".$mailingPseudoId."' AND
794
                p.c_id = $course_id
795
            ";
796
    $result = Database::query($sql);
797
798
    if (!($res = Database::fetch_array($result))) {
799
        die(get_lang('GeneralError').' (code 901)');
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...
800
    }
801
    if ($owner == 0) {
802
        return $res['uploader_id'];
803
    }
804
    if ($res['uploader_id'] == $owner) {
805
        return true;
806
    }
807
    die(get_lang('GeneralError').' (code '.$or_die.')');
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...
808
}
809
810
/**
811
* @author René Haentjens, Ghent University
812
* @todo check if this function is still necessary.
813
*/
814
function removeMoreIfMailing($file_id)
815
{
816
    $course_id = api_get_course_int_id();
817
    // when deleting a mailing zip-file (posted to mailingPseudoId):
818
    // 1. the detail window is no longer reachable, so
819
    //    for all content files, delete mailingPseudoId from person-table
820
    // 2. finding the owner (getUserOwningThisMailing) is no longer possible, so
821
    //    for all content files, replace mailingPseudoId by owner as uploader
822
    $file_id = intval($file_id);
823
    $sql = "SELECT p.dest_user_id
824
            FROM " . Database::get_course_table(TABLE_DROPBOX_POST)." p
825
            WHERE c_id = $course_id AND p.file_id = '".$file_id."'";
826
    $result = Database::query($sql);
827
828
    if ($res = Database::fetch_array($result)) {
829
        $mailingPseudoId = $res['dest_user_id'];
830
        $mailId = get_mail_id_base();
831
        if ($mailingPseudoId > $mailId) {
832
            $sql = "DELETE FROM ".Database::get_course_table(TABLE_DROPBOX_PERSON)."
833
                    WHERE c_id = $course_id AND user_id='".$mailingPseudoId."'";
834
            Database::query($sql);
835
836
            $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FILE)."
837
                    SET uploader_id='" . api_get_user_id()."'
838
                    WHERE c_id = $course_id AND uploader_id='".$mailingPseudoId."'";
839
            Database::query($sql);
840
        }
841
    }
842
}
843
844
/**
845
 * @param array $file
846
 * @param Dropbox_SentWork $work
847
 *
848
 * @return array|null|string
849
 */
850
function store_add_dropbox($file = [], $work = null)
851
{
852
    $_course = api_get_course_info();
853
    $_user = api_get_user_info();
854
855
    if (empty($file)) {
856
        $file = isset($_FILES['file']) ? $_FILES['file'] : null;
857
    }
858
859
    if (empty($work)) {
860
        // Validating the form data
861
        // there are no recipients selected
862
        if (!isset($_POST['recipients']) || count($_POST['recipients']) <= 0) {
863
            return get_lang('YouMustSelectAtLeastOneDestinee');
864
        } else {
865
            // Check if all the recipients are valid
866
            $thisIsAMailing = false;
867
            $thisIsJustUpload = false;
868
            foreach ($_POST['recipients'] as $rec) {
869
                if ($rec == 'mailing') {
870
                    $thisIsAMailing = true;
871
                } elseif ($rec == 'upload') {
872
                    $thisIsJustUpload = true;
873
                } elseif (strpos($rec, 'user_') === 0 && !isCourseMember(substr($rec, strlen('user_')))) {
874
                    Display::addFlash(
875
                        Display::return_message(
876
                            get_lang('InvalideUserDetected'),
877
                            'warning'
878
                        )
879
                    );
880
                    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 null|string|array.
Loading history...
881
                } elseif (strpos($rec, 'group_') !== 0 && strpos($rec, 'user_') !== 0) {
882
                    Display::addFlash(
883
                        Display::return_message(
884
                            get_lang('InvalideGroupDetected'),
885
                            'warning'
886
                        )
887
                    );
888
889
                    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 null|string|array.
Loading history...
890
                }
891
            }
892
        }
893
894
        // we are doing a mailing but an additional recipient is selected
895
        if ($thisIsAMailing && (count($_POST['recipients']) != 1)) {
896
            Display::addFlash(
897
                Display::return_message(
898
                    get_lang('MailingSelectNoOther'),
899
                    'warning'
900
                )
901
            );
902
903
            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 null|string|array.
Loading history...
904
        }
905
906
        // we are doing a just upload but an additional recipient is selected.
907
        // note: why can't this be valid? It is like sending a document to
908
        // yourself AND to a different person (I do this quite often with my e-mails)
909
        if ($thisIsJustUpload && (count($_POST['recipients']) != 1)) {
910
            Display::addFlash(
911
                Display::return_message(
912
                    get_lang('MailingJustUploadSelectNoOther'),
913
                    'warning'
914
                )
915
            );
916
917
            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 null|string|array.
Loading history...
918
        }
919
    }
920
921
    if (empty($file['name'])) {
922
        Display::addFlash(Display::return_message(get_lang('NoFileSpecified'), 'warning'));
923
        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 null|string|array.
Loading history...
924
    }
925
926
    // are we overwriting a previous file or sending a new one
927
    $dropbox_overwrite = false;
928
    if (isset($_POST['cb_overwrite']) && $_POST['cb_overwrite']) {
929
        $dropbox_overwrite = true;
930
    }
931
932
    // doing the upload
933
    $dropbox_filename = $file['name'];
934
    $dropbox_filesize = $file['size'];
935
    $dropbox_filetype = $file['type'];
936
    $dropbox_filetmpname = $file['tmp_name'];
937
938
    // check if the filesize does not exceed the allowed size.
939
    $maxFileSize = api_get_setting('dropbox_max_filesize');
940
    if ($dropbox_filesize <= 0 || $dropbox_filesize > $maxFileSize) {
941
        Display::addFlash(Display::return_message(get_lang('DropboxFileTooBig'), 'warning'));
942
943
        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 null|string|array.
Loading history...
944
    }
945
946
    // check if the file is actually uploaded
947
    if (!is_uploaded_file($dropbox_filetmpname)) { // check user fraud : no clean error msg.
948
        Display::addFlash(Display::return_message(get_lang('TheFileIsNotUploaded'), 'warning'));
949
950
        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 null|string|array.
Loading history...
951
    }
952
953
    $upload_ok = process_uploaded_file($file, true);
954
955
    if (!$upload_ok) {
956
        return null;
957
    }
958
959
    // Try to add an extension to the file if it hasn't got one
960
    $dropbox_filename = add_ext_on_mime($dropbox_filename, $dropbox_filetype);
961
    // Replace dangerous characters
962
    $dropbox_filename = api_replace_dangerous_char($dropbox_filename);
963
    // Transform any .php file in .phps fo security
964
    $dropbox_filename = php2phps($dropbox_filename);
965
966
    //filter extension
967
    if (!filter_extension($dropbox_filename)) {
968
        Display::addFlash(
969
            Display::return_message(
970
                get_lang('UplUnableToSaveFileFilteredExtension'),
971
                'warning'
972
            )
973
        );
974
        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 null|string|array.
Loading history...
975
    }
976
977
    // set title
978
    $dropbox_title = $dropbox_filename;
979
    // note: I think we could better migrate everything from here on to
980
    // separate functions: store_new_dropbox, store_new_mailing, store_just_upload
981
    if ($dropbox_overwrite && empty($work)) {
982
        $dropbox_person = new Dropbox_Person(
983
            $_user['user_id'],
984
            api_is_course_admin(),
985
            api_is_course_tutor()
986
        );
987
        $mailId = get_mail_id_base();
988
        foreach ($dropbox_person->sentWork as $w) {
989
            if ($w->title == $dropbox_filename) {
990
                if (($w->recipients[0]['id'] > $mailId) xor $thisIsAMailing) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $thisIsAMailing does not seem to be defined for all execution paths leading up to this point.
Loading history...
991
                    Display::addFlash(Display::return_message(get_lang('MailingNonMailingError'), 'warning'));
992
                    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 null|string|array.
Loading history...
993
                }
994
                if (($w->recipients[0]['id'] == $_user['user_id']) xor $thisIsJustUpload) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $thisIsJustUpload does not seem to be defined for all execution paths leading up to this point.
Loading history...
995
                    Display::addFlash(Display::return_message(get_lang('MailingJustUploadSelectNoOther'), 'warning'));
996
                    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 null|string|array.
Loading history...
997
                }
998
                $dropbox_filename = $w->filename;
999
                $found = true; // note: do we still need this?
1000
                break;
1001
            }
1002
        }
1003
    } else {  // rename file to login_filename_uniqueId format
1004
        $dropbox_filename = $_user['username']."_".$dropbox_filename."_".uniqid('');
1005
    }
1006
1007
    if (empty($work)) {
1008
        // creating the array that contains all the users who will receive the file
1009
        $new_work_recipients = [];
1010
        foreach ($_POST['recipients'] as $rec) {
1011
            if (strpos($rec, 'user_') === 0) {
1012
                $new_work_recipients[] = substr($rec, strlen('user_'));
1013
            } elseif (strpos($rec, 'group_') === 0) {
1014
                $groupInfo = GroupManager::get_group_properties(substr($rec, strlen('group_')));
1015
                $userList = GroupManager::get_subscribed_users($groupInfo);
1016
                foreach ($userList as $usr) {
1017
                    if (!in_array($usr['user_id'], $new_work_recipients) && $usr['user_id'] != $_user['user_id']) {
1018
                        $new_work_recipients[] = $usr['user_id'];
1019
                    }
1020
                }
1021
            }
1022
        }
1023
    }
1024
1025
    @move_uploaded_file(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for move_uploaded_file(). 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

1025
    /** @scrutinizer ignore-unhandled */ @move_uploaded_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...
1026
        $dropbox_filetmpname,
1027
        api_get_path(SYS_COURSE_PATH).$_course['path'].'/dropbox/'.$dropbox_filename
1028
    );
1029
1030
    $b_send_mail = api_get_course_setting('email_alert_on_new_doc_dropbox');
1031
1032
    if ($b_send_mail && empty($work)) {
1033
        foreach ($new_work_recipients as $recipient_id) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $new_work_recipients does not seem to be defined for all execution paths leading up to this point.
Loading history...
1034
            $recipent_temp = api_get_user_info($recipient_id);
1035
            $additionalParameters = [
1036
                'smsType' => SmsPlugin::NEW_FILE_SHARED_COURSE_BY,
1037
                'userId' => $recipient_id,
1038
                'courseTitle' => $_course['title'],
1039
                'userUsername' => $recipent_temp['username']
1040
            ];
1041
            api_mail_html(
1042
                api_get_person_name(
1043
                    $recipent_temp['firstname'].' '.$recipent_temp['lastname'],
1044
                    null,
1045
                    PERSON_NAME_EMAIL_ADDRESS
1046
                ),
1047
                $recipent_temp['email'],
1048
                get_lang('NewDropboxFileUploaded'),
1049
                get_lang('NewDropboxFileUploadedContent').' <a href="'.api_get_path(WEB_CODE_PATH).'dropbox/index.php?'.api_get_cidreq().'">'.get_lang('SeeFile').'</a>'.
1050
                "\n\n".
1051
                api_get_person_name(
1052
                    $_user['firstName'],
1053
                    $_user['lastName'],
1054
                    null,
1055
                    PERSON_NAME_EMAIL_ADDRESS
1056
                )."\n".get_lang('Email')." : ".$_user['mail'],
1057
                api_get_person_name(
1058
                    $_user['firstName'],
1059
                    $_user['lastName'],
1060
                    null,
1061
                    PERSON_NAME_EMAIL_ADDRESS
1062
                ),
1063
                $_user['mail'],
1064
                null,
1065
                null,
1066
                null,
1067
                $additionalParameters
1068
            );
1069
        }
1070
    }
1071
1072
    if (empty($work)) {
1073
        // Create new
1074
        $result = new Dropbox_SentWork(
1075
            $_user['user_id'],
1076
            $dropbox_title,
1077
            isset($_POST['description']) ? $_POST['description'] : '',
1078
            api_get_user_id(),
1079
            $dropbox_filename,
1080
            $dropbox_filesize,
1081
            $new_work_recipients
1082
        );
1083
    } else {
1084
        // Update
1085
        $work->title = $dropbox_title;
1086
        $work->filename = $dropbox_filename;
1087
        $work->filesize = $dropbox_filesize;
1088
        $work->upload_date = api_get_utc_datetime();
1089
        $work->last_upload_date = api_get_utc_datetime();
1090
        $work->description = isset($_POST['description']) ? $_POST['description'] : '';
1091
        $work->uploader_id = api_get_user_id();
1092
        $work->updateFile();
1093
        $result = $work;
1094
    }
1095
1096
    Security::clear_token();
1097
    Display::addFlash(Display::return_message(get_lang('FileUploadSucces')));
1098
1099
    return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type Dropbox_SentWork which is incompatible with the documented return type null|string|array.
Loading history...
1100
}
1101
1102
/**
1103
 * Transforms the array containing all the feedback into something visually attractive.
1104
 *
1105
 * @param an array containing all the feedback about the given message.
1106
 *
1107
 * @author Patrick Cool <[email protected]>, Ghent University
1108
 * @version march 2006
1109
 */
1110
function feedback($array, $url)
1111
{
1112
    $output = null;
1113
    foreach ($array as $value) {
1114
        $output .= format_feedback($value);
1115
    }
1116
    $output .= feedback_form($url);
1117
    return $output;
1118
}
1119
1120
/**
1121
* This function returns the html code to display the feedback messages on a given dropbox file
1122
* @param $feedback_array an array that contains all the feedback messages about the given document.
1123
* @return string code
1124
* @todo add the form for adding new comment (if the other party has not deleted it yet).
1125
*
1126
* @author Patrick Cool <[email protected]>, Ghent University
1127
* @version march 2006
1128
*/
1129
function format_feedback($feedback)
1130
{
1131
    $userInfo = api_get_user_info($feedback['author_user_id']);
1132
    $output = UserManager::getUserProfileLink($userInfo);
1133
    $output .= '&nbsp;&nbsp;'.Display::dateToStringAgoAndLongDate($feedback['feedback_date']).'<br />';
1134
    $output .= '<div style="padding-top:6px">'.nl2br($feedback['feedback']).'</div><hr size="1" noshade/><br />';
1135
    return $output;
1136
}
1137
1138
/**
1139
* this function returns the code for the form for adding a new feedback message to a dropbox file.
1140
* @param $url  url string
1141
* @return string code
1142
*
1143
* @author Patrick Cool <[email protected]>, Ghent University
1144
* @version march 2006
1145
*/
1146
function feedback_form($url)
1147
{
1148
    $return = '<div class="feeback-form">';
1149
    $number_users_who_see_file = check_if_file_exist($_GET['id']);
1150
    if ($number_users_who_see_file) {
1151
        $token = Security::get_token();
1152
        $return .= '<div class="form-group">';
1153
        $return .= '<input type="hidden" name="sec_token" value="'.$token.'"/>';
1154
        $return .= '<label class="col-sm-3 control-label">'.get_lang('AddNewFeedback');
1155
        $return .= '</label>';
1156
        $return .= '<div class="col-sm-6">';
1157
        $return .= '<textarea name="feedback" class="form-control" rows="4"></textarea>';
1158
        $return .= '</div>';
1159
        $return .= '<div class="col-sm-3">';
1160
        $return .= '<div class="pull-right"><a class="btn btn-default btn-sm" href="'.$url.'"><i class="fa fa-times" aria-hidden="true"></i></a></div>';
1161
        $return .= '<button type="submit" class="btn btn-primary btn-sm" name="store_feedback" value="'.get_lang('Ok').'"
1162
                    onclick="javascript: document.form_dropbox.attributes.action.value = document.location;">'.get_lang('AddComment').'</button>';
1163
        $return .= '</div>';
1164
        $return .= '</div>';
1165
        $return .= '</div>';
1166
    } else {
1167
        $return .= get_lang('AllUsersHaveDeletedTheFileAndWillNotSeeFeedback');
1168
    }
1169
    return $return;
1170
}
1171
1172
function user_can_download_file($id, $user_id)
1173
{
1174
    $course_id = api_get_course_int_id();
1175
    $id = intval($id);
1176
    $user_id = intval($user_id);
1177
1178
    $sql = "SELECT file_id 
1179
            FROM ".Database::get_course_table(TABLE_DROPBOX_PERSON)."
1180
            WHERE c_id = $course_id AND user_id = $user_id AND file_id = ".$id;
1181
    $result = Database::query($sql);
1182
    $number_users_who_see_file = Database::num_rows($result);
1183
1184
    $sql = "SELECT file_id 
1185
            FROM ".Database::get_course_table(TABLE_DROPBOX_POST)."
1186
            WHERE c_id = $course_id AND dest_user_id = $user_id AND file_id = ".$id;
1187
    $result = Database::query($sql);
1188
    $count = Database::num_rows($result);
1189
    return $number_users_who_see_file > 0 || $count > 0;
1190
}
1191
1192
// we now check if the other users have not delete this document yet.
1193
// If this is the case then it is useless to see the
1194
// add feedback since the other users will never get to see the feedback.
1195
function check_if_file_exist($id)
1196
{
1197
    $id = intval($id);
1198
    $course_id = api_get_course_int_id();
1199
    $sql = "SELECT file_id 
1200
            FROM ".Database::get_course_table(TABLE_DROPBOX_PERSON)."
1201
            WHERE c_id = $course_id AND file_id = ".$id;
1202
    $result = Database::query($sql);
1203
    $number_users_who_see_file = Database::num_rows($result);
1204
1205
    $sql = "SELECT file_id 
1206
            FROM ".Database::get_course_table(TABLE_DROPBOX_POST)."
1207
            WHERE c_id = $course_id AND file_id = ".$id;
1208
    $result = Database::query($sql);
1209
    $count = Database::num_rows($result);
1210
    return $number_users_who_see_file > 0 || $count > 0;
1211
}
1212
1213
/**
1214
* @return string language string (depending on the success or failure.
1215
*
1216
* @author Patrick Cool <[email protected]>, Ghent University
1217
* @version march 2006
1218
*/
1219
function store_feedback()
1220
{
1221
    if (!is_numeric($_GET['id'])) {
1222
        return get_lang('FeedbackError');
1223
    }
1224
    $course_id = api_get_course_int_id();
1225
    if (empty($_POST['feedback'])) {
1226
        return get_lang('PleaseTypeText');
1227
    } else {
1228
        $params = [
1229
            'c_id' => $course_id,
1230
            'file_id' => $_GET['id'],
1231
            'author_user_id' => api_get_user_id(),
1232
            'feedback' => $_POST['feedback'],
1233
            'feedback_date' => api_get_utc_datetime(),
1234
        ];
1235
1236
        $id = Database::insert(Database::get_course_table(TABLE_DROPBOX_FEEDBACK), $params);
1237
        if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $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...
1238
            $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FEEDBACK)." 
1239
                    SET feedback_id = iid WHERE iid = $id";
1240
            Database::query($sql);
1241
        }
1242
1243
        return get_lang('DropboxFeedbackStored');
1244
    }
1245
}
1246
1247
/**
1248
* This function downloads all the files of the input array into one zip
1249
* @param array $fileList containing all the ids of the files that have to be downloaded.
1250
* @author Patrick Cool <[email protected]>, Ghent University
1251
* @todo consider removing the check if the user has received or sent this file (zip download of a folder already sufficiently checks for this).
1252
* @todo integrate some cleanup function that removes zip files that are older than 2 days
1253
*
1254
* @author Patrick Cool <[email protected]>, Ghent University
1255
* @author Julio Montoya  Addin c_id support
1256
* @version march 2006
1257
*/
1258
function zip_download($fileList)
1259
{
1260
    $_course = api_get_course_info();
1261
    $course_id = api_get_course_int_id();
1262
    $fileList = array_map('intval', $fileList);
1263
1264
    // note: we also have to add the check if the user has received or sent this file.
1265
    $sql = "SELECT DISTINCT file.filename, file.title, file.author, file.description
1266
            FROM ". Database::get_course_table(TABLE_DROPBOX_FILE)." file
1267
            INNER JOIN ". Database::get_course_table(TABLE_DROPBOX_PERSON)." person
1268
            ON (person.file_id=file.id AND file.c_id = $course_id AND person.c_id = $course_id)
1269
            INNER JOIN ".Database::get_course_table(TABLE_DROPBOX_POST)." post
1270
            ON (post.file_id = file.id AND post.c_id = $course_id AND file.c_id = $course_id)
1271
            WHERE
1272
                file.id IN (".implode(', ', $fileList).") AND
1273
                file.id = person.file_id AND
1274
                (
1275
                    person.user_id = '".api_get_user_id()."' OR
1276
                    post.dest_user_id = '".api_get_user_id()."'
1277
                ) ";
1278
    $result = Database::query($sql);
1279
1280
    $files = [];
1281
    while ($row = Database::fetch_array($result)) {
1282
        $files[$row['filename']] = [
1283
            'filename' => $row['filename'],
1284
            'title' => $row['title'],
1285
            'author' => $row['author'],
1286
            'description' => $row['description']
1287
        ];
1288
    }
1289
1290
    // Step 3: create the zip file and add all the files to it
1291
    $temp_zip_file = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
1292
    Session::write('dropbox_files_to_download', $files);
1293
    $zip = new PclZip($temp_zip_file);
1294
    foreach ($files as $value) {
1295
        $zip->add(
1296
            api_get_path(SYS_COURSE_PATH).$_course['path'].'/dropbox/'.$value['filename'],
1297
            PCLZIP_OPT_REMOVE_ALL_PATH,
1298
            PCLZIP_CB_PRE_ADD,
1299
            'my_pre_add_callback'
1300
        );
1301
    }
1302
    Session::erase('dropbox_files_to_download');
1303
    $name = 'dropbox-'.api_get_utc_datetime().'.zip';
1304
    $result = DocumentManager::file_send_for_download($temp_zip_file, true, $name);
1305
    if ($result === false) {
1306
        api_not_allowed(true);
1307
    }
1308
    @unlink($temp_zip_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

1308
    /** @scrutinizer ignore-unhandled */ @unlink($temp_zip_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...
1309
    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...
1310
}
1311
1312
/**
1313
 * This is a callback function to decrypt the files in the zip file
1314
 * to their normal filename (as stored in the database)
1315
 * @param array $p_event a variable of PCLZip
1316
 * @param array $p_header a variable of PCLZip
1317
 *
1318
 * @author Patrick Cool <[email protected]>, Ghent University
1319
 * @version march 2006
1320
 */
1321
function my_pre_add_callback($p_event, &$p_header)
0 ignored issues
show
Unused Code introduced by
The parameter $p_event is not used and could be removed. ( Ignorable by Annotation )

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

1321
function my_pre_add_callback(/** @scrutinizer ignore-unused */ $p_event, &$p_header)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1322
{
1323
    $files = Session::read('dropbox_files_to_download');
1324
    $p_header['stored_filename'] = $files[$p_header['stored_filename']]['title'];
1325
    return 1;
1326
}
1327
1328
/**
1329
 * @desc Generates the contents of a html file that gives an overview of all the files in the zip file.
1330
 *       This is to know the information of the files that are inside the zip file (who send it, the comment, ...)
1331
 * @author Patrick Cool <[email protected]>, Ghent University, March 2006
1332
 * @author Ivan Tcholakov, 2010, code for html metadata has been added.
1333
 */
1334
function generate_html_overview($files, $dont_show_columns = [], $make_link = [])
1335
{
1336
    $return = '<!DOCTYPE html'."\n";
1337
    $return .= "\t".'PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'."\n";
1338
    $return .= "\t".'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n";
1339
    $return .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.api_get_language_isocode().'" lang="'.api_get_language_isocode().'">'."\n";
1340
1341
    $return .= "<head>\n\t<title>".get_lang('OverviewOfFilesInThisZip')."</title>\n";
1342
    $return .= "\t".'<meta http-equiv="Content-Type" content="text/html; charset='.api_get_system_encoding().'" />'."\n";
1343
    $return .= "</head>\n\n";
1344
    $return .= '<body dir="'.api_get_text_direction().'">'."\n\n";
1345
    $return .= "<table border=\"1px\">\n";
1346
1347
    $counter = 0;
1348
    foreach ($files as $value) {
1349
        // Adding the header.
1350
        if ($counter == 0) {
1351
            $columns_array = array_keys($value);
1352
            $return .= "\n<tr>";
1353
            foreach ($columns_array as $columns_array_key => $columns_array_value) {
1354
                if (!in_array($columns_array_value, $dont_show_columns)) {
1355
                    $return .= "\n\t<th>".$columns_array_value."</th>";
1356
                }
1357
                $column[] = $columns_array_value;
1358
            }
1359
            $return .= "\n</tr>\n";
1360
        }
1361
        $counter++;
1362
1363
        // Adding the content.
1364
        $return .= "\n<tr>";
1365
        foreach ($column as $column_key => $column_value) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $column does not seem to be defined for all execution paths leading up to this point.
Loading history...
1366
            if (!in_array($column_value, $dont_show_columns)) {
1367
                $return .= "\n\t<td>";
1368
                if (in_array($column_value, $make_link)) {
1369
                    $return .= '<a href="'.$value[$column_value].'">'.$value[$column_value].'</a>';
1370
                } else {
1371
                    $return .= $value[$column_value];
1372
                }
1373
                $return .= "</td>";
1374
            }
1375
        }
1376
        $return .= "\n</tr>\n";
1377
    }
1378
    $return .= "\n</table>\n\n</body>";
1379
    $return .= "\n</html>";
1380
1381
    return $return;
1382
}
1383
1384
/**
1385
* @desc This function retrieves the number of feedback messages on every
1386
 * document. This function might become obsolete when
1387
*       the feedback becomes user individual.
1388
* @author Patrick Cool <[email protected]>, Ghent University
1389
* @version march 2006
1390
*/
1391
function get_total_number_feedback($file_id = '')
0 ignored issues
show
Unused Code introduced by
The parameter $file_id is not used and could be removed. ( Ignorable by Annotation )

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

1391
function get_total_number_feedback(/** @scrutinizer ignore-unused */ $file_id = '')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1392
{
1393
    $course_id = api_get_course_int_id();
1394
    $sql = "SELECT COUNT(feedback_id) AS total, file_id
1395
            FROM ". Database::get_course_table(TABLE_DROPBOX_FEEDBACK)."
1396
            WHERE c_id = $course_id GROUP BY file_id";
1397
    $result = Database::query($sql);
1398
    $return = [];
1399
    while ($row = Database::fetch_array($result)) {
1400
        $return[$row['file_id']] = $row['total'];
1401
    }
1402
    return $return;
1403
}
1404
1405
/**
1406
* @desc this function checks if the key exists. If this is the case
1407
 * it returns the value, if not it returns 0
1408
* @author Patrick Cool <[email protected]>, Ghent University
1409
* @version march 2006
1410
*/
1411
function check_number_feedback($key, $array)
1412
{
1413
    if (is_array($array)) {
1414
        if (array_key_exists($key, $array)) {
1415
            return $array[$key];
1416
        } else {
1417
            return 0;
1418
        }
1419
    } else {
1420
        return 0;
1421
    }
1422
}
1423
1424
/**
1425
 * Get the last access to a given tool of a given user
1426
 * @param $tool string the tool constant
1427
 * @param $courseId the course_id
1428
 * @param $user_id the id of the user
1429
 * @return string last tool access date
1430
 *
1431
 * @author Patrick Cool <[email protected]>, Ghent University
1432
 * @version march 2006
1433
 *
1434
 * @todo consider moving this function to a more appropriate place.
1435
 */
1436
function get_last_tool_access($tool, $courseId = null, $user_id = null)
1437
{
1438
    // The default values of the parameters
1439
    if (empty($courseId)) {
1440
        $courseId = api_get_course_int_id();
1441
    }
1442
    if (empty($user_id)) {
1443
        $user_id = api_get_user_id();
1444
    }
1445
1446
    // the table where the last tool access is stored (=track_e_lastaccess)
1447
    $table_last_access = Database::get_main_table('track_e_lastaccess');
1448
1449
    $sql = "SELECT access_date FROM $table_last_access
1450
            WHERE
1451
                access_user_id = ".intval($user_id)." AND
1452
                c_id='".intval($courseId)."' AND
1453
                access_tool='".Database::escape_string($tool)."'
1454
                ORDER BY access_date DESC
1455
                LIMIT 1";
1456
    $result = Database::query($sql);
1457
    $row = Database::fetch_array($result);
1458
    return $row['access_date'];
1459
}
1460
/**
1461
 * Previously $dropbox_cnf['mailingIdBase'], returns a mailing ID to generate a mail ID
1462
 * @return int
1463
 */
1464
function get_mail_id_base()
1465
{
1466
    // false = no mailing functionality
1467
    //$dropbox_cnf['mailingIdBase'] = 10000000;  // bigger than any user_id,
1468
    // allowing enough space for pseudo_ids as uploader_id, dest_user_id, user_id:
1469
    // mailing pseudo_id = dropbox_cnf('mailingIdBase') + mailing id
1470
    return 10000000;
1471
}
1472