Test Setup Failed
Push — master ( c7183e...00c715 )
by Julito
30:43
created

work.lib.php ➔ addDir()   D

Complexity

Conditions 14
Paths 58

Size

Total Lines 117
Code Lines 84

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 84
nc 58
nop 5
dl 0
loc 117
rs 4.9516
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 Chamilo\CourseBundle\Entity\CStudentPublication;
6
7
/**
8
 *  @package chamilo.work
9
 *  @author Thomas, Hugues, Christophe - original version
10
 *  @author Patrick Cool <[email protected]>, Ghent University -
11
 * ability for course admins to specify wether uploaded documents are visible or invisible by default.
12
 *  @author Roan Embrechts, code refactoring and virtual course support
13
 *  @author Frederic Vauthier, directories management
14
 *  @author Julio Montoya <[email protected]> BeezNest 2011 LOTS of bug fixes
15
 *  @todo   this lib should be convert in a static class and moved to main/inc/lib
16
 */
17
18
/**
19
 * Displays action links (for admins, authorized groups members and authorized students)
20
 * @param   string  Current dir
21
 * @param   integer Whether to show tool options
22
 * @param   integer Whether to show upload form option
23
 * @return  void
24
 */
25
function display_action_links($id, $cur_dir_path, $action)
26
{
27
    global $gradebook;
28
29
    $id = $my_back_id = intval($id);
30
    if ($action == 'list') {
31
        $my_back_id = 0;
32
    }
33
34
    $display_output = '';
35
    $origin = api_get_origin();
36
37 View Code Duplication
    if (!empty($id)) {
38
        $display_output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&gradebook='.$gradebook.'&id='.$my_back_id.'">'.
39
            Display::return_icon('back.png', get_lang('BackToWorksList'), '', ICON_SIZE_MEDIUM).'</a>';
40
    }
41
42
    if (api_is_allowed_to_edit(null, true) && $origin != 'learnpath') {
43
        // Create dir
44
        if (empty($id)) {
45
            $display_output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=create_dir&gradebook='.$gradebook.'">';
46
            $display_output .= Display::return_icon('new_work.png', get_lang('CreateAssignment'), '', ICON_SIZE_MEDIUM).'</a>';
47
        }
48
        if (empty($id)) {
49
            // Options
50
            $display_output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=settings&gradebook='.$gradebook.'">';
51
            $display_output .= Display::return_icon('settings.png', get_lang('EditToolOptions'), '', ICON_SIZE_MEDIUM).'</a>';
52
        }
53
        $display_output .= '<a id="open-view-list" href="#">'.Display::return_icon('listwork.png', get_lang('ViewStudents'), '', ICON_SIZE_MEDIUM).'</a>';
54
55
    }
56
57
    if (api_is_allowed_to_edit(null, true) && $origin != 'learnpath' && api_is_allowed_to_session_edit(false, true)) {
58
        // Delete all files
59
        if (api_get_setting('permanently_remove_deleted_files') == 'true') {
60
            $message = get_lang('ConfirmYourChoiceDeleteAllfiles');
61
        } else {
62
            $message = get_lang('ConfirmYourChoice');
63
        }
64
    }
65
66
    if ($display_output != '') {
67
        echo '<div class="actions">';
68
        echo $display_output;
69
        echo '</div>';
70
    }
71
}
72
73
/**
74
 * Returns a form displaying all options for this tool.
75
 * These are
76
 * - make all files visible / invisible
77
 * - set the default visibility of uploaded files
78
 * @param $defaults
79
 * @return string The HTML form
80
 */
81
function settingsForm($defaults)
82
{
83
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
84
85
    if (!$is_allowed_to_edit) {
86
        return;
87
    }
88
89
    $url = api_get_path(WEB_CODE_PATH).'work/work.php?'.api_get_cidreq().'&action=settings';
90
    $form = new FormValidator('edit_settings', 'post', $url);
91
    $form->addElement('hidden', 'changeProperties', 1);
92
    $form->addElement('header', get_lang('EditToolOptions'));
93
94
    $group = array(
95
        $form->createElement('radio', 'show_score', null, get_lang('NewVisible'), 0),
96
        $form->createElement('radio', 'show_score', null, get_lang('NewUnvisible'), 1)
97
    );
98
    $form->addGroup($group, '', get_lang('DefaultUpload'));
99
100
    $group = array(
101
        $form->createElement('radio', 'student_delete_own_publication', null, get_lang('Yes'), 1),
102
        $form->createElement('radio', 'student_delete_own_publication', null, get_lang('No'), 0)
103
    );
104
    $form->addGroup($group, '', get_lang('StudentAllowedToDeleteOwnPublication'));
105
    $form->addButtonSave(get_lang('Save'));
106
    $form->setDefaults($defaults);
107
108
    return $form->returnForm();
109
}
110
111
/**
112
 * @param string $path
113
 * @param int $courseId
114
 *
115
 * @return array
116
 */
117 View Code Duplication
function get_work_data_by_path($path, $courseId = null)
118
{
119
    $path = Database::escape_string($path);
120
    if (empty($courseId)) {
121
        $courseId = api_get_course_int_id();
122
    } else {
123
        $courseId = intval($courseId);
124
    }
125
126
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
127
    $sql = "SELECT *  FROM  ".$work_table."
128
            WHERE url = '$path' AND c_id = $courseId ";
129
    $result = Database::query($sql);
130
    $return = array();
131
    if (Database::num_rows($result)) {
132
        $return = Database::fetch_array($result, 'ASSOC');
133
    }
134
135
    return $return;
136
}
137
138
/**
139
 * @param int $id
140
 * @param int $courseId
141
 * @param int $sessionId
142
 * @return array
143
 */
144
function get_work_data_by_id($id, $courseId = null, $sessionId = null)
145
{
146
    $id = intval($id);
147
148
    if (!empty($courseId)) {
149
        $courseId = intval($courseId);
150
    } else {
151
        $courseId = api_get_course_int_id();
152
    }
153
154
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
155
156
    $sessionCondition = null;
157
    if (!empty($sessionId)) {
158
        $sessionCondition = api_get_session_condition($sessionId, true);
159
    }
160
161
    $sql = "SELECT * FROM $table
162
            WHERE
163
                id = $id AND c_id = $courseId
164
                $sessionCondition";
165
    $result = Database::query($sql);
166
    $work = array();
167
    if (Database::num_rows($result)) {
168
        $work = Database::fetch_array($result, 'ASSOC');
169
        if (empty($work['title'])) {
170
            $work['title'] = basename($work['url']);
171
        }
172
        $work['download_url'] = api_get_path(WEB_CODE_PATH).'work/download.php?id='.$work['id'].'&'.api_get_cidreq();
173
        $work['view_url'] = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$work['id'].'&'.api_get_cidreq();
174
        $work['show_url'] = api_get_path(WEB_CODE_PATH).'work/show_file.php?id='.$work['id'].'&'.api_get_cidreq();
175
        $work['show_content'] = '';
176
        if ($work['contains_file']) {
177
            $fileInfo = pathinfo($work['title']);
178
            if (is_array($fileInfo) &&
179
                !empty($fileInfo['extension']) &&
180
                in_array($fileInfo['extension'], array('jpg', 'png', 'gif'))
181
            ) {
182
                $work['show_content'] = '<img src="'.$work['show_url'].'"/>';
183
            }
184
        }
185
186
        $fieldValue = new ExtraFieldValue('work');
187
        $work['extra'] = $fieldValue->getAllValuesForAnItem(
188
            $id,
189
            true
190
        );
191
192
    }
193
194
    return $work;
195
}
196
197
/**
198
 * @param int $user_id
199
 * @param int $work_id
200
 *
201
 * @return int
202
 */
203
function get_work_count_by_student($user_id, $work_id)
204
{
205
    $user_id = intval($user_id);
206
    $work_id = intval($work_id);
207
    $course_id = api_get_course_int_id();
208
    $session_id = api_get_session_id();
209
    $sessionCondition = api_get_session_condition($session_id);
210
211
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
212
    $sql = "SELECT COUNT(*) as count
213
            FROM  $table
214
            WHERE
215
                c_id = $course_id AND
216
                parent_id = $work_id AND
217
                user_id = $user_id AND
218
                active IN (0, 1)
219
                $sessionCondition";
220
    $result = Database::query($sql);
221
    $return = 0;
222
    if (Database::num_rows($result)) {
223
        $return = Database::fetch_row($result, 'ASSOC');
224
        $return = intval($return[0]);
225
    }
226
227
    return $return;
228
}
229
230
/**
231
 * @param int $id
232
 * @param int $courseId
233
 *
234
 * @return array
235
 */
236 View Code Duplication
function get_work_assignment_by_id($id, $courseId = null)
237
{
238
    if (empty($courseId)) {
239
        $courseId = api_get_course_int_id();
240
    } else {
241
        $courseId = intval($courseId);
242
    }
243
    $id = intval($id);
244
245
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
246
    $sql = "SELECT * FROM $table
247
            WHERE c_id = $courseId AND publication_id = $id";
248
    $result = Database::query($sql);
249
    $return = array();
250
    if (Database::num_rows($result)) {
251
        $return = Database::fetch_array($result, 'ASSOC');
252
    }
253
254
    return $return;
255
}
256
257
/**
258
 * @param int $id
259
 * @param array $my_folder_data
260
 * @param string $add_in_where_query
261
 * @param int $course_id
262
 * @param int $session_id
263
 *
264
 * @return array
265
 */
266
function getWorkList($id, $my_folder_data, $add_in_where_query = null, $course_id = 0, $session_id = 0)
267
{
268
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
269
270
    $course_id = $course_id ? $course_id : api_get_course_int_id();
271
    $session_id = $session_id ? $session_id : api_get_session_id();
272
    $condition_session = api_get_session_condition($session_id);
273
    $group_id = api_get_group_id();
274
275
    $groupIid = 0;
276
    if ($group_id) {
277
        $groupInfo = GroupManager::get_group_properties($group_id);
278
        $groupIid = $groupInfo['iid'];
279
    }
280
281
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
282
283
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
284
        api_get_course_int_id(),
285
        3,
286
        $id,
287
        api_get_session_id()
288
    );
289
290
    if ($linkInfo) {
291
        $workInGradeBookLinkId = $linkInfo['id'];
292
        if ($workInGradeBookLinkId) {
293
            if ($is_allowed_to_edit) {
294
                if (intval($my_folder_data['qualification']) == 0) {
295
                    echo Display::return_message(
296
                        get_lang('MaxWeightNeedToBeProvided'),
297
                        'warning'
298
                    );
299
                }
300
            }
301
        }
302
    }
303
304
    $contains_file_query = '';
305
306
    // Get list from database
307
    if ($is_allowed_to_edit) {
308
        $active_condition = ' active IN (0, 1)';
309
        $sql = "SELECT * FROM $work_table
310
                WHERE
311
                    c_id = $course_id
312
                    $add_in_where_query
313
                    $condition_session AND
314
                    $active_condition AND
315
                    (parent_id = 0)
316
                    $contains_file_query AND 
317
                    post_group_id = $groupIid
318
                ORDER BY sent_date DESC";
319
    } else {
320 View Code Duplication
        if (!empty($group_id)) {
321
            // set to select only messages posted by the user's group
322
            $group_query = " WHERE c_id = $course_id AND post_group_id = $groupIid";
323
            $subdirs_query = " AND parent_id = 0";
324
        } else {
325
            $group_query = " WHERE c_id = $course_id AND (post_group_id = '0' OR post_group_id is NULL) ";
326
            $subdirs_query = " AND parent_id = 0";
327
        }
328
        //@todo how we can active or not an assignment?
329
        $active_condition = ' AND active IN (1, 0)';
330
        $sql = "SELECT * FROM  $work_table
331
                $group_query
332
                $subdirs_query
333
                $add_in_where_query
334
                $active_condition
335
                $condition_session
336
                ORDER BY title";
337
    }
338
339
    $work_parents = array();
340
341
    $sql_result = Database::query($sql);
342
    if (Database::num_rows($sql_result)) {
343
        while ($work = Database::fetch_object($sql_result)) {
344
            if ($work->parent_id == 0) {
345
                $work_parents[] = $work;
346
            }
347
        }
348
    }
349
350
    return $work_parents;
351
}
352
353
/**
354
 * @param int $userId
355
 * @param int $courseId
356
 * @param int $sessionId
357
 * @return array
358
 */
359
function getWorkPerUser($userId, $courseId = 0, $sessionId = 0)
360
{
361
    $works = getWorkList(null, null, null, $courseId, $sessionId);
362
    $result = array();
363
    if (!empty($works)) {
364
        foreach ($works as $workData) {
365
            $workId = $workData->id;
366
            $result[$workId]['work'] = $workData;
367
            $result[$workId]['work']->user_results = get_work_user_list(
368
                0,
369
                100,
370
                null,
371
                null,
372
                $workId,
373
                null,
374
                $userId,
375
                false,
376
                $courseId,
377
                $sessionId
378
            );
379
        }
380
    }
381
    return $result;
382
}
383
384
/**
385
 * @param int $workId
386
 * @param int $groupId
387
 * @param int $course_id
388
 * @param int $sessionId
389
 * @return mixed
390
 */
391
function getUniqueStudentAttemptsTotal($workId, $groupId, $course_id, $sessionId)
392
{
393
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
394
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
395
    $course_id = intval($course_id);
396
    $workId = intval($workId);
397
    $sessionId = intval($sessionId);
398
    $groupId = intval($groupId);
399
    $sessionCondition = api_get_session_condition(
400
        $sessionId,
401
        true,
402
        false,
403
        'w.session_id'
404
    );
405
406
    $groupIid = 0;
407
    if ($groupId) {
408
        $groupInfo = GroupManager::get_group_properties($groupId);
409
        $groupIid = $groupInfo['iid'];
410
    }
411
412
    $sql = "SELECT count(DISTINCT u.user_id)
413
            FROM $work_table w
414
            INNER JOIN $user_table u
415
            ON w.user_id = u.user_id
416
            WHERE
417
                w.c_id = $course_id
418
                $sessionCondition AND
419
                w.parent_id = $workId AND
420
                w.post_group_id = $groupIid AND
421
                w.active IN (0, 1)
422
            ";
423
424
    $res_document = Database::query($sql);
425
    $rowCount = Database::fetch_row($res_document);
426
427
    return $rowCount[0];
428
}
429
430
/**
431
 * @param mixed $workId
432
 * @param int $groupId
433
 * @param int $course_id
434
 * @param int $sessionId
435
 * @param int $userId user id to filter
436
 * @param array $onlyUserList only parse this user list
437
 * @return mixed
438
 */
439
function getUniqueStudentAttempts(
440
    $workId,
441
    $groupId,
442
    $course_id,
443
    $sessionId,
444
    $userId = null,
445
    $onlyUserList = array()
446
) {
447
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
448
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
449
450
    $course_id = intval($course_id);
451
    $workCondition = null;
452
    if (is_array($workId)) {
453
        $workId = array_map('intval', $workId);
454
        $workId = implode("','", $workId);
455
        $workCondition = " w.parent_id IN ('".$workId."') AND";
456
    } else {
457
        $workId = intval($workId);
458
        $workCondition = " w.parent_id = ".$workId." AND";
459
    }
460
461
    $sessionId = intval($sessionId);
462
    $groupId = intval($groupId);
463
    $studentCondition = null;
464
465 View Code Duplication
    if (!empty($onlyUserList)) {
466
        $onlyUserList = array_map('intval', $onlyUserList);
467
        $studentCondition = "AND u.user_id IN ('".implode("', '", $onlyUserList)."') ";
468
    } else {
469
        if (empty($userId)) {
470
            return 0;
471
        }
472
    }
473
474
    $groupIid = 0;
475
    if ($groupId) {
476
        $groupInfo = GroupManager::get_group_properties($groupId);
477
        $groupIid = $groupInfo['iid'];
478
    }
479
480
    $sessionCondition = api_get_session_condition(
481
        $sessionId,
482
        true,
483
        false,
484
        'w.session_id'
485
    );
486
487
    $sql = "SELECT count(*) FROM (
488
                SELECT count(*), w.parent_id
489
                FROM $work_table w
490
                INNER JOIN $user_table u
491
                ON w.user_id = u.user_id
492
                WHERE
493
                    w.filetype = 'file' AND
494
                    w.c_id = $course_id
495
                    $sessionCondition AND
496
                    $workCondition
497
                    w.post_group_id = $groupIid AND
498
                    w.active IN (0, 1) $studentCondition
499
                ";
500
    if (!empty($userId)) {
501
        $userId = intval($userId);
502
        $sql .= " AND u.user_id = ".$userId;
503
    }
504
    $sql .= " GROUP BY u.user_id, w.parent_id) as t";
505
    $result = Database::query($sql);
506
    $row = Database::fetch_row($result);
507
508
    return $row[0];
509
}
510
511
/**
512
 * Shows the work list (student view)
513
 * @return string
514
 */
515
function showStudentWorkGrid()
516
{
517
    $courseInfo = api_get_course_info();
518
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_student&'.api_get_cidreq();
519
520
    $columns = array(
521
        get_lang('Type'),
522
        get_lang('Title'),
523
        get_lang('HandOutDateLimit'),
524
        get_lang('Feedback'),
525
        get_lang('LastUpload')
526
    );
527
528
    $columnModel = array(
529
        array('name'=>'type', 'index'=>'type', 'width'=>'30', 'align'=>'center', 'sortable' => 'false'),
530
        array('name'=>'title', 'index'=>'title', 'width'=>'250', 'align'=>'left'),
531
        array('name'=>'expires_on', 'index'=>'expires_on', 'width'=>'80', 'align'=>'center', 'sortable'=>'false'),
532
        array('name'=>'feedback', 'index'=>'feedback', 'width'=>'80', 'align'=>'center', 'sortable'=>'false'),
533
        array('name'=>'last_upload', 'index'=>'feedback', 'width'=>'125', 'align'=>'center', 'sortable'=>'false')
534
    );
535
536 View Code Duplication
    if ($courseInfo['show_score'] == 0) {
537
        $columnModel[] = array(
538
            'name' => 'others',
539
            'index' => 'others',
540
            'width' => '80',
541
            'align' => 'left',
542
            'sortable' => 'false'
543
        );
544
        $columns[] = get_lang('Others');
545
    }
546
547
    $params = array(
548
        'autowidth' => 'true',
549
        'height' => 'auto'
550
    );
551
552
    $html = '<script>
553
        $(function() {
554
            '.Display::grid_js('workList', $url, $columns, $columnModel, $params, array(), null, true).'
555
        });
556
    </script>';
557
558
    $html .= Display::grid_html('workList');
559
    return $html;
560
}
561
562
/**
563
 * Shows the work list (teacher view)
564
 * @return string
565
 */
566
function showTeacherWorkGrid()
567
{
568
    $columnModel = array(
569
        array('name'=>'type', 'index'=>'type', 'width'=>'35', 'align'=>'center', 'sortable' => 'false'),
570
        array('name'=>'title', 'index'=>'title', 'width'=>'300', 'align'=>'left', 'wrap_cell' => "true"),
571
        array('name'=>'sent_date', 'index'=>'sent_date', 'width'=>'125', 'align'=>'center'),
572
        array('name'=>'expires_on', 'index'=>'expires_on', 'width'=>'125', 'align'=>'center'),
573
        array('name'=>'amount', 'index'=>'amount', 'width'=>'110', 'align'=>'center', 'sortable' => 'false'),
574
        array('name'=>'actions', 'index'=>'actions', 'width'=>'110', 'align'=>'left', 'sortable'=>'false')
575
    );
576
577
    $token = null;
578
579
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_teacher&'.api_get_cidreq();
580
    $deleteUrl = api_get_path(WEB_AJAX_PATH).'work.ajax.php?a=delete_work&'.api_get_cidreq();
581
582
    $columns = array(
583
        get_lang('Type'),
584
        get_lang('Title'),
585
        get_lang('SentDate'),
586
        get_lang('HandOutDateLimit'),
587
        get_lang('AmountSubmitted'),
588
        get_lang('Actions')
589
    );
590
591
    $params = array(
592
        'multiselect' => true,
593
        'autowidth' => 'true',
594
        'height' => 'auto'
595
    );
596
597
    $html = '<script>
598
    $(function() {
599
        '.Display::grid_js('workList', $url, $columns, $columnModel, $params, array(), null, true).'
600
        $("#workList").jqGrid(
601
            "navGrid",
602
            "#workList_pager",
603
            { edit: false, add: false, del: true },
604
            { height:280, reloadAfterSubmit:false }, // edit options
605
            { height:280, reloadAfterSubmit:false }, // add options
606
            { reloadAfterSubmit:false, url: "'.$deleteUrl.'" }, // del options
607
            { width:500 } // search options
608
        );
609
    });
610
    </script>';
611
    $html .= Display::grid_html('workList');
612
    return $html;
613
}
614
615
/**
616
 * Builds the form thats enables the user to
617
 * select a directory to browse/upload in
618
 * This function has been copied from the document/document.inc.php library
619
 *
620
 * @param array $folders
621
 * @param string $curdirpath
622
 * @param string $group_dir
623
 * @return string html form
624
 */
625
// TODO: This function is a candidate for removal, it is not used anywhere.
626
function build_work_directory_selector($folders, $curdirpath, $group_dir = '')
627
{
628
    $form = '<form name="selector" action="'.api_get_self().'?'.api_get_cidreq().'" method="POST">';
629
    $form .= get_lang('CurrentDirectory').' <select name="curdirpath" onchange="javascript: document.selector.submit();">';
630
    //group documents cannot be uploaded in the root
631
    if ($group_dir == '') {
632
        $form .= '<option value="/">/ ('.get_lang('Root').')</option>';
633
        if (is_array($folders)) {
634
            foreach ($folders as $folder) {
635
                $selected = ($curdirpath == $folder) ? ' selected="selected"' : '';
636
                $form .= '<option'.$selected.' value="'.$folder.'">'.$folder.'</option>'."\n";
637
            }
638
        }
639
    } else {
640
        foreach ($folders as $folder) {
641
            $selected = ($curdirpath == $folder) ? ' selected="selected"' : '';
642
            $display_folder = substr($folder, strlen($group_dir));
643
            $display_folder = ($display_folder == '') ? '/ ('.get_lang('Root').')' : $display_folder;
644
            $form .= '<option'.$selected.' value="'.$folder.'">'.$display_folder.'</option>'."\n";
645
        }
646
    }
647
648
    $form .= '</select>';
649
    $form .= '<noscript><input type="submit" name="change_path" value="'.get_lang('Ok').'" /></noscript>';
650
    $form .= '</form>';
651
652
    return $form;
653
}
654
655
/**
656
 * Builds the form thats enables the user to
657
 * move a document from one directory to another
658
 * This function has been copied from the document/document.inc.php library
659
 *
660
 * @param array $folders
661
 * @param string $curdirpath
662
 * @param string $move_file
663
 * @param string $group_dir
664
 * @return string html form
665
 */
666
function build_work_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
667
{
668
    $course_id = api_get_course_int_id();
669
    $move_file = intval($move_file);
670
    $tbl_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
671
    $sql = "SELECT title, url FROM $tbl_work
672
            WHERE c_id = $course_id AND id ='".$move_file."'";
673
    $result = Database::query($sql);
674
    $row = Database::fetch_array($result, 'ASSOC');
675
    $title = empty($row['title']) ? basename($row['url']) : $row['title'];
676
677
    $form = new FormValidator(
678
        'move_to_form',
679
        'post',
680
        api_get_self().'?'.api_get_cidreq().'&curdirpath='.Security::remove_XSS($curdirpath)
681
    );
682
683
    $form->addHeader(get_lang('MoveFile').' - '.Security::remove_XSS($title));
684
    $form->addHidden('item_id', $move_file);
685
    $form->addHidden('action', 'move_to');
686
687
    //group documents cannot be uploaded in the root
688
    if ($group_dir == '') {
689
        if ($curdirpath != '/') {
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...
690
            //$form .= '<option value="0">/ ('.get_lang('Root').')</option>';
691
        }
692
        if (is_array($folders)) {
693
            foreach ($folders as $fid => $folder) {
694
                //you cannot move a file to:
695
                //1. current directory
696
                //2. inside the folder you want to move
697
                //3. inside a subfolder of the folder you want to move
698
                if (($curdirpath != $folder) && ($folder != $move_file) && (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')) {
699
                    //$form .= '<option value="'.$fid.'">'.$folder.'</option>';
700
                    $options[$fid] = $folder;
701
                }
702
            }
703
        }
704
    } else {
705
        if ($curdirpath != '/') {
706
            $form .= '<option value="0">/ ('.get_lang('Root').')</option>';
707
        }
708
        foreach ($folders as $fid => $folder) {
709
            if (($curdirpath != $folder) && ($folder != $move_file) && (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')) {
710
                //cannot copy dir into his own subdir
711
                $display_folder = substr($folder, strlen($group_dir));
712
                $display_folder = ($display_folder == '') ? '/ ('.get_lang('Root').')' : $display_folder;
713
                //$form .= '<option value="'.$fid.'">'.$display_folder.'</option>'."\n";
714
                $options[$fid] = $display_folder;
715
            }
716
        }
717
    }
718
719
    $form->addSelect('move_to_id', get_lang('Select'), $options);
720
    $form->addButtonSend(get_lang('MoveFile'), 'move_file_submit');
721
722
    return $form->returnForm();
723
}
724
725
/**
726
 * creates a new directory trying to find a directory name
727
 * that doesn't already exist
728
 *
729
 * @author Hugues Peeters <[email protected]>
730
 * @author Bert Vanderkimpen
731
 * @author Yannick Warnier <[email protected]> Adaptation for work tool
732
 * @param  string $base_work_dir Base work dir (.../work)
733
 * @param  string $desiredDirName complete path of the desired name
0 ignored issues
show
Bug introduced by
There is no parameter named $desiredDirName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
734
 *
735
 * @return  string actual directory name if it succeeds, boolean false otherwise
736
 */
737
function create_unexisting_work_directory($base_work_dir, $desired_dir_name)
738
{
739
    $nb = '';
740
    $base_work_dir = (substr($base_work_dir, -1, 1) == '/' ? $base_work_dir : $base_work_dir.'/');
741
    while (file_exists($base_work_dir.$desired_dir_name.$nb)) {
742
        $nb += 1;
743
    }
744
745
    if (@mkdir($base_work_dir.$desired_dir_name.$nb, api_get_permissions_for_new_directories())) {
746
        return $desired_dir_name.$nb;
747
    } else {
748
        return false;
749
    }
750
}
751
752
/**
753
 * Delete a work-tool directory
754
 * @param   int  $id work directory id to delete
755
 * @return  integer -1 on error
756
 */
757
function deleteDirWork($id)
758
{
759
    $locked = api_resource_is_locked_by_gradebook($id, LINK_STUDENTPUBLICATION);
760
761
    if ($locked == true) {
762
        echo Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
763
        return false;
764
    }
765
766
    $_course = api_get_course_info();
767
    $id = intval($id);
768
    $work_data = get_work_data_by_id($id);
769
770
    if (empty($work_data)) {
771
        return false;
772
    }
773
774
    $base_work_dir = api_get_path(SYS_COURSE_PATH).$_course['path'].'/work';
775
    $work_data_url = $base_work_dir.$work_data['url'];
776
    $check = Security::check_abs_path($work_data_url.'/', $base_work_dir.'/');
777
778
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
779
    $TSTDPUBASG = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
780
    $t_agenda = Database::get_course_table(TABLE_AGENDA);
781
782
    $course_id = api_get_course_int_id();
783
    $sessionId = api_get_session_id();
784
785
    if (!empty($work_data['url'])) {
786
        if ($check) {
787
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
788
789
            if (!empty($consideredWorkingTime)) {
790
                $fieldValue = new ExtraFieldValue('work');
791
                $resultExtra = $fieldValue->getAllValuesForAnItem(
792
                    $work_data['id'],
793
                    true
794
                );
795
796
                $workingTime = null;
797
798 View Code Duplication
                foreach ($resultExtra as $field) {
799
                    $field = $field['value'];
800
                    if ($consideredWorkingTime == $field->getField()->getVariable()) {
801
                        $workingTime = $field->getValue();
802
803
                        break;
804
                    }
805
                }
806
807
                $courseUsers = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
808
809
                if (!empty($workingTime)) {
810
                    foreach ($courseUsers as $user) {
0 ignored issues
show
Bug introduced by
The expression $courseUsers of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
811
                        $userWorks = get_work_user_list(
812
                            0,
813
                            100,
814
                            null,
815
                            null,
816
                            $work_data['id'],
817
                            null,
818
                            $user['user_id'],
819
                            false,
820
                            $course_id,
821
                            $sessionId
822
                        );
823
824
                        if (count($userWorks) != 1) {
825
                            continue;
826
                        }
827
828
                        Event::eventRemoveVirtualCourseTime($course_id, $user['user_id'], $sessionId, $workingTime);
829
                    }
830
                }
831
            }
832
833
            // Deleting all contents inside the folder
834
            $sql = "UPDATE $table SET active = 2
835
                    WHERE c_id = $course_id AND filetype = 'folder' AND id = $id";
836
            Database::query($sql);
837
838
            $sql = "UPDATE $table SET active = 2
839
                    WHERE c_id = $course_id AND parent_id = $id";
840
            Database::query($sql);
841
842
            $new_dir = $work_data_url.'_DELETED_'.$id;
843
844 View Code Duplication
            if (api_get_setting('permanently_remove_deleted_files') == 'true') {
845
                my_delete($work_data_url);
846
            } else {
847
                if (file_exists($work_data_url)) {
848
                    rename($work_data_url, $new_dir);
849
                }
850
            }
851
852
            // Gets calendar_id from student_publication_assigment
853
            $sql = "SELECT add_to_calendar FROM $TSTDPUBASG
854
                    WHERE c_id = $course_id AND publication_id = $id";
855
            $res = Database::query($sql);
856
            $calendar_id = Database::fetch_row($res);
857
858
            // delete from agenda if it exists
859
            if (!empty($calendar_id[0])) {
860
                $sql = "DELETE FROM $t_agenda
861
                        WHERE c_id = $course_id AND id = '".$calendar_id[0]."'";
862
                Database::query($sql);
863
            }
864
            $sql = "DELETE FROM $TSTDPUBASG
865
                    WHERE c_id = $course_id AND publication_id = $id";
866
            Database::query($sql);
867
868
            Event::addEvent(
869
                LOG_WORK_DIR_DELETE,
870
                LOG_WORK_DATA,
871
                [
872
                    'id' => $work_data['id'],
873
                    'url' => $work_data['url'],
874
                    'title' => $work_data['title']
875
                ],
876
                null,
877
                api_get_user_id(),
878
                api_get_course_int_id(),
879
                $sessionId
880
            );
881
882
            $link_info = GradebookUtils::isResourceInCourseGradebook(
883
                api_get_course_int_id(),
884
                3,
885
                $id,
886
                api_get_session_id()
887
            );
888
            $link_id = $link_info['id'];
889
            if ($link_info !== false) {
890
                GradebookUtils::remove_resource_from_course_gradebook($link_id);
891
            }
892
            return true;
893
        }
894
    }
895
}
896
897
/**
898
 * Get the path of a document in the student_publication table (path relative to the course directory)
899
 * @param   integer $id
900
 * @return  string  Path (or -1 on error)
901
 */
902
function get_work_path($id)
903
{
904
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
905
    $course_id = api_get_course_int_id();
906
    $sql = 'SELECT url FROM '.$table.'
907
            WHERE c_id = '.$course_id.' AND id='.intval($id);
908
    $res = Database::query($sql);
909
    if (Database::num_rows($res)) {
910
        $row = Database::fetch_array($res);
911
        return $row['url'];
912
    }
913
    return -1;
914
}
915
916
/**
917
 * Update the url of a work in the student_publication table
918
 * @param integer $id of the work to update
919
 * @param string  $new_path Destination directory where the work has been moved (must end with a '/')
920
 * @param int $parent_id
921
 *
922
 * @return mixed Int -1 on error, sql query result on success
923
 */
924
function updateWorkUrl($id, $new_path, $parent_id)
925
{
926
    if (empty($id)) {
927
        return -1;
928
    }
929
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
930
    $course_id = api_get_course_int_id();
931
    $id = intval($id);
932
    $parent_id = intval($parent_id);
933
934
    $sql = "SELECT * FROM $table
935
            WHERE c_id = $course_id AND id = $id";
936
    $res = Database::query($sql);
937
    if (Database::num_rows($res) != 1) {
938
        return -1;
939
    } else {
940
        $row = Database::fetch_array($res);
941
        $filename = basename($row['url']);
942
        $new_url = $new_path.$filename;
943
        $new_url = Database::escape_string($new_url);
944
945
        $sql = "UPDATE $table SET
946
                   url = '$new_url',
947
                   parent_id = '$parent_id'
948
                WHERE c_id = $course_id AND id = $id";
949
        $res = Database::query($sql);
950
951
        return $res;
952
    }
953
}
954
955
/**
956
 * Update the url of a dir in the student_publication table
957
 * @param  array $work_data work original data
958
 * @param  string $newPath Example: "folder1"
959
 * @return bool
960
 */
961
function updateDirName($work_data, $newPath)
962
{
963
    $course_id = $work_data['c_id'];
964
    $sessionId = intval($work_data['session_id']);
965
    $work_id = intval($work_data['iid']);
966
    $oldPath = $work_data['url'];
967
    $originalNewPath = Database::escape_string($newPath);
968
    $newPath = Database::escape_string($newPath);
969
    $newPath = api_replace_dangerous_char($newPath);
970
    $newPath = disable_dangerous_file($newPath);
971
972
    if ($oldPath == '/'.$newPath) {
973
        return true;
974
    }
975
976
    if (!empty($newPath)) {
977
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
978
        $sql = "UPDATE $table SET
979
                    title = '".$originalNewPath."'
980
                WHERE
981
                    c_id = $course_id AND
982
                    iid = $work_id";
983
        Database::query($sql);
984
    }
985
}
986
987
/**
988
 * Return an array with all the folder's ids that are in the given path
989
 * @param   string Path of the directory
990
 * @return  array The list of ids of all the directories in the path
991
 * @author  Julio Montoya
992
 * @version April 2008
993
 */
994
function get_parent_directories($id)
995
{
996
    $course_id = api_get_course_int_id();
997
    $em = Database::getManager();
998
999
    $directories = $em
1000
        ->getRepository('ChamiloCourseBundle:CStudentPublication')
1001
        ->findBy([
1002
            'cId' => $course_id,
1003
            'parentId' => $id
1004
        ]);
1005
1006
    $list_id = array();
1007
1008
    foreach ($directories as $directory) {
1009
        $list_id[] = $directory->getId();
1010
    }
1011
1012
    return $list_id;
1013
}
1014
1015
/**
1016
 * Transform an all directory structure (only directories) in an array
1017
 * @param   string path of the directory
1018
 * @return  array the directory structure into an array
1019
 * @author  Julio Montoya
1020
 * @version April 2008
1021
 */
1022 View Code Duplication
function directory_to_array($directory)
1023
{
1024
    $array_items = array();
1025
    if ($handle = @opendir($directory)) {
1026
        while (false !== ($file = readdir($handle))) {
1027
            if ($file != '.' && $file != '..') {
1028
                if (is_dir($directory.'/'.$file)) {
1029
                    $array_items = array_merge($array_items, directory_to_array($directory.'/'.$file));
1030
                    $file = $directory.'/'.$file;
1031
                    $array_items[] = preg_replace("/\/\//si", '/', $file);
1032
                }
1033
            }
1034
        }
1035
        closedir($handle);
1036
    }
1037
1038
    return $array_items;
1039
}
1040
1041
/**
1042
 * Insert into the DB of the course all the directories
1043
 * @param   string $base_work_dir path of the /work directory of the course
1044
 * @return  mixed Int -1 on error, sql query result on success
1045
 * @author  Julio Montoya
1046
 * @version April 2008
1047
 * @param string $base_work_dir
1048
 */
1049
1050
function insert_all_directory_in_course_table($base_work_dir)
1051
{
1052
    $dir_to_array = directory_to_array($base_work_dir, true);
1053
    $only_dir = array();
1054
1055
    for ($i = 0; $i < count($dir_to_array); $i++) {
1056
        $only_dir[] = substr($dir_to_array[$i], strlen($base_work_dir), strlen($dir_to_array[$i]));
1057
    }
1058
    $course_id = api_get_course_int_id();
1059
    $group_id  = api_get_group_id();
1060
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1061
    $groupIid = 0;
1062
    if ($group_id) {
1063
        $groupInfo = GroupManager::get_group_properties($group_id);
1064
        $groupIid = $groupInfo['iid'];
1065
    }
1066
1067
    for ($i = 0; $i < count($only_dir); $i++) {
1068
        $url = $only_dir[$i];
1069
1070
        $params = [
1071
            'c_id' => $course_id,
1072
            'url' => $url,
1073
            'title' => '',
1074
            'description' => '',
1075
            'author' => '',
1076
            'active' => '1',
1077
            'accepted' => '1',
1078
            'filetype' => 'folder',
1079
            'post_group_id' => $groupIid,
1080
        ];
1081
1082
        Database::insert($work_table, $params);
1083
    }
1084
}
1085
1086
/**
1087
 * This function displays the number of files contained in a directory
1088
 *
1089
 * @param   string the path of the directory
1090
 * @param   boolean true if we want the total quantity of files
1091
 * include in others child directories, false only  files in the directory
1092
 * @return  array the first element is an integer with the number of files
1093
 * in the folder, the second element is the number of directories
1094
 * @author  Julio Montoya
1095
 * @version April 2008
1096
 */
1097
function count_dir($path_dir, $recurse)
1098
{
1099
    $count = 0;
1100
    $count_dir = 0;
1101
    $d = dir($path_dir);
1102
    while ($entry = $d->Read()) {
1103
        if (!(($entry == '..') || ($entry == '.'))) {
1104
            if (is_dir($path_dir.'/'.$entry)) {
1105
                $count_dir++;
1106
                if ($recurse) {
1107
                    $count += count_dir($path_dir.'/'.$entry, $recurse);
1108
                }
1109
            } else {
1110
                $count++;
1111
            }
1112
        }
1113
    }
1114
    $return_array = array();
1115
    $return_array[] = $count;
1116
    $return_array[] = $count_dir;
1117
    return $return_array;
1118
}
1119
1120
/**
1121
 * returns all the javascript that is required for easily
1122
 * validation when you create a work
1123
 * this goes into the $htmlHeadXtra[] array
1124
 */
1125
function to_javascript_work()
1126
{
1127
    $js = '<script>
1128
        function updateDocumentTitle(value) {
1129
            var temp = value.indexOf("/");
1130
            //linux path
1131
            if(temp!=-1){
1132
                var temp=value.split("/");
1133
            } else {
1134
                var temp=value.split("\\\");
1135
            }
1136
            document.getElementById("file_upload").value=temp[temp.length-1];
1137
            $("#contains_file_id").attr("value", 1);
1138
        }
1139
1140
        function checkDate(month, day, year) {
1141
          var monthLength =
1142
            new Array(31,28,31,30,31,30,31,31,30,31,30,31);
1143
1144
          if (!day || !month || !year)
1145
            return false;
1146
1147
          // check for bisestile year
1148
          if (year/4 == parseInt(year/4))
1149
            monthLength[1] = 29;
1150
1151
          if (month < 1 || month > 12)
1152
            return false;
1153
1154
          if (day > monthLength[month-1])
1155
            return false;
1156
1157
          return true;
1158
        }
1159
1160
        function mktime() {
1161
1162
            var no, ma = 0, mb = 0, i = 0, d = new Date(), argv = arguments, argc = argv.length;
1163
            d.setHours(0,0,0); d.setDate(1); d.setMonth(1); d.setYear(1972);
1164
1165
            var dateManip = {
1166
                0: function(tt){ return d.setHours(tt); },
1167
                1: function(tt){ return d.setMinutes(tt); },
1168
                2: function(tt){ set = d.setSeconds(tt); mb = d.getDate() - 1; return set; },
1169
                3: function(tt){ set = d.setMonth(parseInt(tt)-1); ma = d.getFullYear() - 1972; return set; },
1170
                4: function(tt){ return d.setDate(tt+mb); },
1171
                5: function(tt){ return d.setYear(tt+ma); }
1172
            };
1173
1174
            for( i = 0; i < argc; i++ ){
1175
                no = parseInt(argv[i]*1);
1176
                if (isNaN(no)) {
1177
                    return false;
1178
                } else {
1179
                    // arg is number, lets manipulate date object
1180
                    if(!dateManip[i](no)){
1181
                        // failed
1182
                        return false;
1183
                    }
1184
                }
1185
            }
1186
            return Math.floor(d.getTime()/1000);
1187
        }
1188
1189
        function setFocus() {
1190
            $("#work_title").focus();
1191
        }
1192
1193
        $(document).ready(function() {
1194
            setFocus();
1195
1196
            var checked = $("#expiry_date").attr("checked");
1197
            if (checked) {
1198
                $("#option2").show();                
1199
            } else {
1200
                $("#option2").hide();                
1201
            }
1202
            
1203
            var checkedEndDate = $("#end_date").attr("checked");            
1204
            if (checkedEndDate) {                
1205
                $("#option3").show();
1206
                $("#ends_on").attr("checked", true);
1207
            } else {
1208
                $("#option3").hide();                
1209
                $("#ends_on").attr("checked", false);
1210
            }
1211
1212
            $("#expiry_date").click(function() {
1213
                $("#option2").toggle();
1214
            });
1215
1216
            $("#end_date").click(function() {
1217
                $("#option3").toggle();
1218
            });
1219
        });
1220
    </script>';
1221
1222
    return $js;
1223
}
1224
1225
/**
1226
 * Gets the id of a student publication with a given path
1227
 * @param string $path
1228
 * @return true if is found / false if not found
1229
 */
1230
// TODO: The name of this function does not fit with the kind of information it returns. Maybe check_work_id() or is_work_id()?
1231
function get_work_id($path)
1232
{
1233
    $TBL_STUDENT_PUBLICATION = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1234
    $TBL_PROP_TABLE = Database::get_course_table(TABLE_ITEM_PROPERTY);
1235
    $course_id = api_get_course_int_id();
1236
    $path = Database::escape_string($path);
1237
1238
    if (api_is_allowed_to_edit()) {
1239
        $sql = "SELECT work.id
1240
                FROM $TBL_STUDENT_PUBLICATION AS work, $TBL_PROP_TABLE AS props
1241
                WHERE
1242
                    props.c_id = $course_id AND
1243
                    work.c_id = $course_id AND
1244
                    props.tool='work' AND
1245
                    work.id=props.ref AND
1246
                    work.url LIKE 'work/".$path."%' AND
1247
                    work.filetype='file' AND
1248
                    props.visibility<>'2'";
1249
    } else {
1250
        $sql = "SELECT work.id
1251
                FROM $TBL_STUDENT_PUBLICATION AS work, $TBL_PROP_TABLE AS props
1252
                WHERE
1253
                    props.c_id = $course_id AND
1254
                    work.c_id = $course_id AND
1255
                    props.tool='work' AND
1256
                    work.id=props.ref AND
1257
                    work.url LIKE 'work/".$path."%' AND
1258
                    work.filetype='file' AND
1259
                    props.visibility<>'2' AND
1260
                    props.lastedit_user_id = '".api_get_user_id()."'";
1261
    }
1262
    $result = Database::query($sql);
1263
    $num_rows = Database::num_rows($result);
1264
1265
    if ($result && $num_rows > 0) {
1266
        return true;
1267
    } else {
1268
        return false;
1269
    }
1270
}
1271
1272
/**
1273
 * @param int $work_id
1274
 * @param int $onlyMeUserId show only my works
1275
 * @param int $notMeUserId show works from everyone except me
1276
 * @return int
1277
 */
1278
function get_count_work($work_id, $onlyMeUserId = null, $notMeUserId = null)
1279
{
1280
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1281
    $iprop_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1282
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
1283
1284
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
1285
    $session_id = api_get_session_id();
1286
    $condition_session = api_get_session_condition(
1287
        $session_id,
1288
        true,
1289
        false,
1290
        'work.session_id'
1291
    );
1292
1293
    $group_id = api_get_group_id();
1294
    $course_info = api_get_course_info();
1295
    $course_id = $course_info['real_id'];
1296
    $work_id = intval($work_id);
1297
1298
    $groupIid = 0;
1299
    if ($group_id) {
1300
        $groupInfo = GroupManager::get_group_properties($group_id);
1301
        $groupIid = $groupInfo['iid'];
1302
    }
1303
1304 View Code Duplication
    if (!empty($group_id)) {
1305
        // set to select only messages posted by the user's group
1306
        $extra_conditions = " work.post_group_id = '".intval($groupIid)."' ";
1307
    } else {
1308
        $extra_conditions = " (work.post_group_id = '0' or work.post_group_id IS NULL) ";
1309
    }
1310
1311 View Code Duplication
    if ($is_allowed_to_edit) {
1312
        $extra_conditions .= ' AND work.active IN (0, 1) ';
1313
    } else {
1314
        $extra_conditions .= ' AND work.active IN (0, 1) AND accepted = 1';
1315
        if (isset($course_info['show_score']) && $course_info['show_score'] == 1) {
1316
            $extra_conditions .= " AND work.user_id = ".api_get_user_id()." ";
1317
        } else {
1318
            $extra_conditions .= '';
1319
        }
1320
    }
1321
1322
    $extra_conditions .= " AND parent_id  = ".$work_id."  ";
1323
1324
    $where_condition = null;
1325
1326
    if (!empty($notMeUserId)) {
1327
        $where_condition .= " AND u.user_id <> ".intval($notMeUserId);
1328
    }
1329
1330
    if (!empty($onlyMeUserId)) {
1331
        $where_condition .= " AND u.user_id =  ".intval($onlyMeUserId);
1332
    }
1333
1334
    $sql = "SELECT count(*) as count
1335
            FROM $iprop_table prop
1336
            INNER JOIN $work_table work
1337
            ON (
1338
                prop.ref = work.id AND
1339
                prop.c_id = $course_id AND
1340
                prop.tool='work' AND
1341
                prop.visibility <> 2 AND
1342
                work.c_id = $course_id
1343
            )
1344
            INNER JOIN $user_table u 
1345
            ON (work.user_id = u.user_id)
1346
            WHERE $extra_conditions $where_condition $condition_session";
1347
1348
    $result = Database::query($sql);
1349
1350
    $users_with_work = 0;
1351
    if (Database::num_rows($result)) {
1352
        $result = Database::fetch_array($result);
1353
        $users_with_work = $result['count'];
1354
    }
1355
    return $users_with_work;
1356
}
1357
1358
/**
1359
 * @param int $start
1360
 * @param int $limit
1361
 * @param string $column
1362
 * @param string $direction
1363
 * @param string $where_condition
1364
 * @param bool $getCount
1365
 * @return array
1366
 */
1367
function getWorkListStudent(
1368
    $start,
1369
    $limit,
1370
    $column,
1371
    $direction,
1372
    $where_condition,
1373
    $getCount = false
1374
) {
1375
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1376
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1377
    $courseInfo = api_get_course_info();
1378
    $course_id = $courseInfo['real_id'];
1379
    $session_id = api_get_session_id();
1380
    $condition_session = api_get_session_condition($session_id);
1381
    $group_id = api_get_group_id();
1382
    $userId = api_get_user_id();
1383
1384
    $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
1385
        api_get_user_id(),
1386
        $courseInfo
1387
    );
1388
1389
    if (!in_array($direction, array('asc', 'desc'))) {
1390
        $direction = 'desc';
1391
    }
1392
    if (!empty($where_condition)) {
1393
        $where_condition = ' AND '.$where_condition;
1394
    }
1395
1396
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1397
    $start = intval($start);
1398
    $limit = intval($limit);
1399
1400
    $groupIid = 0;
1401
    if ($group_id) {
1402
        $groupInfo = GroupManager::get_group_properties($group_id);
1403
        $groupIid = $groupInfo['iid'];
1404
    }
1405
    $groupIid = (int) $groupIid;
1406
1407
    // Get list from database
1408 View Code Duplication
    if (!empty($groupIid)) {
1409
        $group_query = " WHERE w.c_id = $course_id AND post_group_id = $groupIid";
1410
        $subdirs_query = "AND parent_id = 0";
1411
    } else {
1412
        $group_query = " WHERE w.c_id = $course_id AND (post_group_id = '0' or post_group_id is NULL)  ";
1413
        $subdirs_query = "AND parent_id = 0";
1414
    }
1415
1416
    $active_condition = ' AND active IN (1, 0)';
1417
1418
    if ($getCount) {
1419
        $select = "SELECT count(w.id) as count ";
1420
    } else {
1421
        $select = "SELECT w.*, a.expires_on, expires_on, ends_on, enable_qualification ";
1422
    }
1423
1424
    $sql = "$select
1425
            FROM $workTable w
1426
            LEFT JOIN $workTableAssignment a
1427
            ON (a.publication_id = w.id AND a.c_id = w.c_id)
1428
                $group_query
1429
                $subdirs_query
1430
                $active_condition
1431
                $condition_session
1432
                $where_condition
1433
            ";
1434
1435
    $sql .= " ORDER BY $column $direction ";
1436
1437
    if (!empty($start) && !empty($limit)) {
1438
        $sql .= " LIMIT $start, $limit";
1439
    }
1440
1441
    $result = Database::query($sql);
1442
1443
    if ($getCount) {
1444
        $row = Database::fetch_array($result);
1445
        return $row['count'];
1446
    }
1447
1448
    $works = array();
1449
    $url = api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq();
1450
    if ($isDrhOfCourse) {
1451
        $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq();
1452
    }
1453
1454
    $urlOthers = api_get_path(WEB_CODE_PATH).'work/work_list_others.php?'.api_get_cidreq().'&id=';
1455
    while ($work = Database::fetch_array($result, 'ASSOC')) {
1456
        $isSubscribed = userIsSubscribedToWork($userId, $work['id'], $course_id);
1457
        if ($isSubscribed == false) {
1458
            continue;
1459
        }
1460
1461
        $visibility = api_get_item_visibility($courseInfo, 'work', $work['id'], $session_id);
1462
1463
        if ($visibility != 1) {
1464
            continue;
1465
        }
1466
1467
        $work['type'] = Display::return_icon('work.png');
1468
        $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1469
1470
        if (empty($work['title'])) {
1471
            $work['title'] = basename($work['url']);
1472
        }
1473
1474
        $whereCondition = " AND u.user_id = ".intval($userId);
1475
1476
        $workList = get_work_user_list(
1477
            0,
1478
            1000,
1479
            null,
1480
            null,
1481
            $work['id'],
1482
            $whereCondition
1483
        );
1484
1485
        $count = getTotalWorkComment($workList, $courseInfo);
1486
        $lastWork = getLastWorkStudentFromParentByUser($userId, $work, $courseInfo);
1487
1488
        if (!is_null($count) && !empty($count)) {
1489
            $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$lastWork['id'].'&'.api_get_cidreq();
1490
1491
            $feedback = '&nbsp;'.Display::url(
1492
                Display::returnFontAwesomeIcon('comments-o'),
1493
                $urlView,
1494
                ['title' => get_lang('View')]
1495
            );
1496
1497
            $work['feedback'] = ' '.Display::label($count.' '.get_lang('Feedback'), 'info').$feedback;
1498
1499
        }
1500
1501
        if (!empty($lastWork)) {
1502
            $work['last_upload'] = (!empty($lastWork['qualification'])) ? $lastWork['qualification_rounded'].' - ' : '';
1503
            $work['last_upload'] .= api_get_local_time($lastWork['sent_date']);
1504
        }
1505
1506
        $work['title'] = Display::url($work['title'], $url.'&id='.$work['id']);
1507
        $work['others'] = Display::url(
1508
            Display::return_icon('group.png', get_lang('Others')),
1509
            $urlOthers.$work['id']
1510
        );
1511
        $works[] = $work;
1512
    }
1513
1514
    return $works;
1515
}
1516
1517
/**
1518
 * @param int $start
1519
 * @param int $limit
1520
 * @param string $column
1521
 * @param string $direction
1522
 * @param string $where_condition
1523
 * @param bool $getCount
1524
 * @return array
1525
 */
1526
function getWorkListTeacher(
1527
    $start,
1528
    $limit,
1529
    $column,
1530
    $direction,
1531
    $where_condition,
1532
    $getCount = false
1533
) {
1534
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1535
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1536
1537
    $courseInfo = api_get_course_info();
1538
    $course_id = api_get_course_int_id();
1539
    $session_id = api_get_session_id();
1540
    $condition_session = api_get_session_condition($session_id);
1541
    $group_id = api_get_group_id();
1542
    $groupIid = 0;
1543
    if ($group_id) {
1544
        $groupInfo = GroupManager::get_group_properties($group_id);
1545
        $groupIid = $groupInfo['iid'];
1546
    }
1547
    $groupIid = (int) $groupIid;
1548
1549
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
1550
    if (!in_array($direction, array('asc', 'desc'))) {
1551
        $direction = 'desc';
1552
    }
1553
    if (!empty($where_condition)) {
1554
        $where_condition = ' AND '.$where_condition;
1555
    }
1556
1557
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1558
    $start = intval($start);
1559
    $limit = intval($limit);
1560
    $works = array();
1561
1562
    // Get list from database
1563
    if ($is_allowed_to_edit) {
1564
        $active_condition = ' active IN (0, 1)';
1565
        if ($getCount) {
1566
            $select = " SELECT count(w.id) as count";
1567
        } else {
1568
            $select = " SELECT w.*, a.expires_on, expires_on, ends_on, enable_qualification ";
1569
        }
1570
        $sql = " $select
1571
                FROM $workTable w
1572
                LEFT JOIN $workTableAssignment a
1573
                ON (a.publication_id = w.id AND a.c_id = w.c_id)
1574
                WHERE
1575
                    w.c_id = $course_id
1576
                    $condition_session AND
1577
                    $active_condition AND
1578
                    parent_id = 0 AND
1579
                    post_group_id = $groupIid
1580
                    $where_condition
1581
                ORDER BY $column $direction
1582
                LIMIT $start, $limit";
1583
1584
        $result = Database::query($sql);
1585
1586
        if ($getCount) {
1587
            $row = Database::fetch_array($result);
1588
1589
            return $row['count'];
1590
        }
1591
        $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq();
1592
        while ($work = Database::fetch_array($result, 'ASSOC')) {
1593
            $workId = $work['id'];
1594
            $work['type'] = Display::return_icon('work.png');
1595
            $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1596
1597
            $countUniqueAttempts = getUniqueStudentAttemptsTotal(
1598
                $workId,
1599
                $group_id,
1600
                $course_id,
1601
                $session_id
1602
            );
1603
1604
            $totalUsers = getStudentSubscribedToWork(
1605
                $workId,
1606
                $course_id,
1607
                $group_id,
1608
                $session_id,
1609
                true
1610
            );
1611
1612
            $work['amount'] = Display::label(
1613
                $countUniqueAttempts.'/'.
1614
                $totalUsers,
1615
                'success'
1616
            );
1617
1618
            $visibility = api_get_item_visibility($courseInfo, 'work', $workId, $session_id);
1619
1620
            if ($visibility == 1) {
1621
                $icon = 'visible.png';
1622
                $text = get_lang('Visible');
1623
                $action = 'invisible';
1624
                $class = '';
1625
            } else {
1626
                $icon = 'invisible.png';
1627
                $text = get_lang('Invisible');
1628
                $action = 'visible';
1629
                $class = 'muted';
1630
            }
1631
1632
            $visibilityLink = Display::url(
1633
                Display::return_icon($icon, $text, array(), ICON_SIZE_SMALL),
1634
                api_get_path(WEB_CODE_PATH).'work/work.php?id='.$workId.'&action='.$action.'&'.api_get_cidreq()
1635
            );
1636
1637
            if (empty($work['title'])) {
1638
                $work['title'] = basename($work['url']);
1639
            }
1640
            $work['title'] = Display::url($work['title'], $url.'&id='.$workId, ['class' => $class]);
1641
            $work['title'] .= ' '.Display::label(get_count_work($work['id']), 'success');
1642
            $work['sent_date'] = api_get_local_time($work['sent_date']);
1643
1644
            $editLink = Display::url(
1645
                Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL),
1646
                api_get_path(WEB_CODE_PATH).'work/edit_work.php?id='.$workId.'&'.api_get_cidreq()
1647
            );
1648
1649
            $correctionLink = '&nbsp;'.Display::url(
1650
                Display::return_icon('upload_package.png', get_lang('UploadCorrections'), '', ICON_SIZE_SMALL),
1651
                api_get_path(WEB_CODE_PATH).'work/upload_corrections.php?'.api_get_cidreq().'&id='.$workId
1652
            ).'&nbsp;';
1653
1654
            if ($countUniqueAttempts > 0) {
1655
                $downloadLink = Display::url(
1656
                    Display::return_icon(
1657
                        'save_pack.png',
1658
                        get_lang('Save'),
1659
                        array(),
1660
                        ICON_SIZE_SMALL
1661
                    ),
1662
                    api_get_path(WEB_CODE_PATH).'work/downloadfolder.inc.php?id='.$workId.'&'.api_get_cidreq()
1663
                );
1664
            } else {
1665
                $downloadLink = Display::url(
1666
                    Display::return_icon(
1667
                        'save_pack_na.png',
1668
                        get_lang('Save'),
1669
                        array(),
1670
                        ICON_SIZE_SMALL
1671
                    ),
1672
                    '#'
1673
                );
1674
            }
1675
            // Remove Delete Work Button from action List
1676
            // Because removeXSS "removes" the onClick JS Event to do the action (See model.ajax.php - Line 1639)
1677
            // But still can use the another jqgrid button to remove works (trash icon)
1678
            //
1679
            // $deleteUrl = api_get_path(WEB_CODE_PATH).'work/work.php?id='.$workId.'&action=delete_dir&'.api_get_cidreq();
1680
            // $deleteLink = '<a href="#" onclick="showConfirmationPopup(this, \'' . $deleteUrl . '\' ) " >' .
1681
            //     Display::return_icon(
1682
            //         'delete.png',
1683
            //         get_lang('Delete'),
1684
            //         array(),
1685
            //         ICON_SIZE_SMALL
1686
            //     ) . '</a>';
1687
1688
            if (!api_is_allowed_to_edit()) {
1689
                // $deleteLink = null;
1690
                $editLink = null;
1691
            }
1692
            $work['actions'] = $visibilityLink.$correctionLink.$downloadLink.$editLink;
1693
            $works[] = $work;
1694
        }
1695
    }
1696
1697
    return $works;
1698
}
1699
1700
/**
1701
 * @param int $start
1702
 * @param int $limit
1703
 * @param string $column
1704
 * @param string $direction
1705
 * @param int $workId
1706
 * @param int $studentId
1707
 * @param string $whereCondition
1708
 * @param bool $getCount
1709
 * @return array
1710
 */
1711
function get_work_user_list_from_documents(
1712
    $start,
1713
    $limit,
1714
    $column,
1715
    $direction,
1716
    $workId,
1717
    $studentId = null,
1718
    $whereCondition = '',
1719
    $getCount = false
1720
) {
1721
    if ($getCount) {
1722
        $select1 = " SELECT count(u.user_id) as count ";
1723
        $select2 = " SELECT count(u.user_id) as count ";
1724
    } else {
1725
        $select1 = " SELECT DISTINCT u.firstname, u.lastname, u.user_id, w.title, w.parent_id, w.document_id document_id, w.id, qualification, qualificator_id";
1726
        $select2 = " SELECT DISTINCT u.firstname, u.lastname, u.user_id, d.title, w.parent_id, d.id document_id, 0, 0, 0";
1727
    }
1728
1729
    $documentTable = Database::get_course_table(TABLE_DOCUMENT);
1730
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1731
    $workRelDocument = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
1732
    $userTable = Database::get_main_table(TABLE_MAIN_USER);
1733
1734
    $courseId = api_get_course_int_id();
1735
    $sessionId = api_get_session_id();
1736
1737
    if (empty($studentId)) {
1738
        $studentId = api_get_user_id();
1739
    }
1740
    $studentId = intval($studentId);
1741
    $workId = intval($workId);
1742
1743
    $userCondition = " AND u.user_id = $studentId ";
1744
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'w.session_id');
1745
    $workCondition = " AND w_rel.work_id = $workId";
1746
    $workParentCondition = " AND w.parent_id = $workId";
1747
1748
    $sql = "(
1749
                $select1 FROM $userTable u
1750
                INNER JOIN $workTable w
1751
                ON (u.user_id = w.user_id AND w.active IN (0, 1) AND w.filetype = 'file')
1752
                WHERE
1753
                    w.c_id = $courseId
1754
                    $userCondition
1755
                    $sessionCondition
1756
                    $whereCondition
1757
                    $workParentCondition
1758
            ) UNION (
1759
                $select2 FROM $workTable w
1760
                INNER JOIN $workRelDocument w_rel
1761
                ON (w_rel.work_id = w.id AND w.active IN (0, 1) AND w_rel.c_id = w.c_id)
1762
                INNER JOIN $documentTable d
1763
                ON (w_rel.document_id = d.id AND d.c_id = w.c_id)
1764
                INNER JOIN $userTable u ON (u.user_id = $studentId)
1765
                WHERE
1766
                    w.c_id = $courseId
1767
                    $workCondition
1768
                    $sessionCondition AND
1769
                    d.id NOT IN (
1770
                        SELECT w.document_id id
1771
                        FROM $workTable w
1772
                        WHERE
1773
                            user_id = $studentId AND
1774
                            c_id = $courseId AND
1775
                            filetype = 'file' AND
1776
                            active IN (0, 1)
1777
                            $sessionCondition
1778
                            $workParentCondition
1779
                    )
1780
            )";
1781
1782
    $start = intval($start);
1783
    $limit = intval($limit);
1784
1785
    $direction = in_array(strtolower($direction), array('desc', 'asc')) ? $direction : 'desc';
1786
    $column = Database::escape_string($column);
1787
1788 View Code Duplication
    if ($getCount) {
1789
        $result = Database::query($sql);
1790
        $result = Database::fetch_array($result);
1791
        return $result['count'];
1792
    }
1793
1794
    $sql .= " ORDER BY $column $direction";
1795
    $sql .= " LIMIT $start, $limit";
1796
1797
    $result = Database::query($sql);
1798
1799
    $currentUserId = api_get_user_id();
1800
    $work_data = get_work_data_by_id($workId);
1801
1802
    $qualificationExists = false;
1803
1804 View Code Duplication
    if (!empty($work_data['qualification']) && intval($work_data['qualification']) > 0) {
1805
        $qualificationExists = true;
1806
    }
1807
1808
    $urlAdd = api_get_path(WEB_CODE_PATH).'work/upload_from_template.php?'.api_get_cidreq();
1809
    $urlEdit = api_get_path(WEB_CODE_PATH).'work/edit.php?'.api_get_cidreq();
1810
    $urlDelete = api_get_path(WEB_CODE_PATH).'work/work_list.php?action=delete&'.api_get_cidreq();
1811
    $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq();
1812
1813
    $editIcon = Display::return_icon('edit.png', get_lang('Edit'));
1814
    $addIcon = Display::return_icon('add.png', get_lang('Add'));
1815
    $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'));
1816
    $viewIcon = Display::return_icon('rate_work.png', get_lang('CorrectAndRate'));
1817
    $allowEdition = api_get_course_setting('student_delete_own_publication');
1818
1819
    $workList = array();
1820
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1821
        $userId = $row['user_id'];
1822
        $documentId = $row['document_id'];
1823
        $itemId = $row['id'];
1824
        $addLinkShowed = false;
1825
1826
        if (empty($documentId)) {
1827
            $url = $urlEdit.'&item_id='.$row['id'].'&id='.$workId;
1828
            $editLink = Display::url($editIcon, $url);
1829
            if ($allowEdition == false) {
1830
                $editLink = null;
1831
            }
1832
        } else {
1833
            $documentToWork = getDocumentToWorkPerUser($documentId, $workId, $courseId, $sessionId, $userId);
1834
1835
            if (empty($documentToWork)) {
1836
                $url = $urlAdd.'&document_id='.$documentId.'&id='.$workId;
1837
                $editLink = Display::url($addIcon, $url);
1838
                $addLinkShowed = true;
1839
            } else {
1840
                $row['title'] = $documentToWork['title'];
1841
                $row['sent_date'] = $documentToWork['sent_date'];
1842
                $newWorkId = $documentToWork['id'];
1843
                $url = $urlEdit.'&item_id='.$newWorkId.'&id='.$workId;
1844
                $editLink = Display::url($editIcon, $url);
1845
1846
                if ($allowEdition == false) {
1847
                    $editLink = null;
1848
                }
1849
            }
1850
        }
1851
1852
        if ($allowEdition && !empty($itemId)) {
1853
            $deleteLink = Display::url($deleteIcon, $urlDelete.'&item_id='.$itemId.'&id='.$workId);
1854
        } else {
1855
            $deleteLink = null;
1856
        }
1857
1858
        $viewLink = null;
1859
        if (!empty($itemId)) {
1860
            $viewLink = Display::url($viewIcon, $urlView.'&id='.$itemId);
1861
        }
1862
1863
        $row['type'] = null;
1864
1865
        if ($qualificationExists) {
1866 View Code Duplication
            if (empty($row['qualificator_id'])) {
1867
                $status = Display::label(get_lang('NotRevised'), 'warning');
1868
            } else {
1869
                $status = Display::label(get_lang('Revised'), 'success');
1870
            }
1871
            $row['qualificator_id'] = $status;
1872
        }
1873
1874
        if (!empty($row['qualification'])) {
1875
            $row['qualification'] = Display::label($row['qualification'], 'info');
1876
        }
1877
1878
        if (!empty($row['sent_date'])) {
1879
            $row['sent_date'] = api_get_local_time($row['sent_date']);
1880
        }
1881
1882
        if ($userId == $currentUserId) {
1883
            $row['actions'] = $viewLink.$editLink.$deleteLink;
1884
        }
1885
1886
        if ($addLinkShowed) {
1887
            $row['qualification'] = '';
1888
            $row['qualificator_id'] = '';
1889
        }
1890
1891
        $workList[] = $row;
1892
    }
1893
1894
    return $workList;
1895
}
1896
1897
/**
1898
 * @param int $start
1899
 * @param int $limit
1900
 * @param int $column
1901
 * @param string $direction
1902
 * @param int $work_id
1903
 * @param array $where_condition
1904
 * @param int $studentId
1905
 * @param bool $getCount
1906
 * @param int $courseId
1907
 * @param int $sessionId
1908
 * @return array
1909
 */
1910
function get_work_user_list(
1911
    $start,
1912
    $limit,
1913
    $column,
1914
    $direction,
1915
    $work_id,
1916
    $where_condition = null,
1917
    $studentId = null,
1918
    $getCount = false,
1919
    $courseId = 0,
1920
    $sessionId = 0
1921
) {
1922
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1923
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
1924
1925
    $session_id = $sessionId ? $sessionId : api_get_session_id();
1926
    $group_id = api_get_group_id();
1927
    $course_info = api_get_course_info();
1928
    $course_info = empty($course_info) ? api_get_course_info_by_id($courseId) : $course_info;
1929
    $course_id = isset($course_info['real_id']) ? $course_info['real_id'] : $courseId;
1930
1931
    $work_id = intval($work_id);
1932
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1933
    $start = intval($start);
1934
    $limit = intval($limit);
1935
1936
    if (!in_array($direction, array('asc', 'desc'))) {
1937
        $direction = 'desc';
1938
    }
1939
1940
    $work_data = get_work_data_by_id($work_id, $courseId, $sessionId);
1941
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
1942
    $condition_session = api_get_session_condition(
1943
        $session_id,
1944
        true,
1945
        false,
1946
        'work.session_id'
1947
    );
1948
    $locked = api_resource_is_locked_by_gradebook(
1949
        $work_id,
1950
        LINK_STUDENTPUBLICATION,
1951
        $course_info['code']
1952
    );
1953
1954
    $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
1955
        api_get_user_id(),
1956
        $course_info
1957
    );
1958
1959
    $groupIid = 0;
1960
    if ($group_id) {
1961
        $groupInfo = GroupManager::get_group_properties($group_id);
1962
        $groupIid = $groupInfo['iid'];
1963
    }
1964
1965
    if (!empty($work_data)) {
1966 View Code Duplication
        if (!empty($group_id)) {
1967
            $extra_conditions = " work.post_group_id = '".intval($groupIid)."' ";
1968
            // set to select only messages posted by the user's group
1969
        } else {
1970
            $extra_conditions = " (work.post_group_id = '0' OR work.post_group_id is NULL) ";
1971
        }
1972
1973 View Code Duplication
        if ($is_allowed_to_edit || $isDrhOfCourse) {
1974
            $extra_conditions .= ' AND work.active IN (0, 1) ';
1975
        } else {
1976
            if (isset($course_info['show_score']) &&
1977
                $course_info['show_score'] == 1
1978
            ) {
1979
                $extra_conditions .= " AND (u.user_id = ".api_get_user_id()." AND work.active IN (0, 1)) ";
1980
            } else {
1981
                $extra_conditions .= ' AND work.active IN (0, 1) ';
1982
            }
1983
        }
1984
1985
        $extra_conditions .= " AND parent_id  = ".$work_id." ";
1986
1987
        $select = 'SELECT DISTINCT
1988
                        u.user_id,
1989
                        work.id as id,
1990
                        title as title,
1991
                        description,
1992
                        url,
1993
                        sent_date,
1994
                        contains_file,
1995
                        has_properties,
1996
                        view_properties,
1997
                        qualification,
1998
                        weight,
1999
                        allow_text_assignment,
2000
                        u.firstname,
2001
                        u.lastname,
2002
                        u.username,
2003
                        parent_id,
2004
                        accepted,
2005
                        qualificator_id,
2006
                        url_correction,
2007
                        title_correction
2008
                        ';
2009
        if ($getCount) {
2010
            $select = "SELECT DISTINCT count(u.user_id) as count ";
2011
        }
2012
2013
        $work_assignment = get_work_assignment_by_id($work_id, $courseId);
2014
2015
        if (!empty($studentId)) {
2016
            $where_condition .= " AND u.user_id = ".intval($studentId);
2017
        }
2018
2019
        $sql = " $select
2020
                FROM $work_table work 
2021
                INNER JOIN $user_table u  
2022
                ON (work.user_id = u.user_id)
2023
                WHERE
2024
                    work.c_id = $course_id AND
2025
                    $extra_conditions 
2026
                    $where_condition 
2027
                    $condition_session
2028
                    AND u.status != ".INVITEE."
2029
                ORDER BY $column $direction";
2030
2031
        if (!empty($start) && !empty($limit)) {
2032
            $sql .= " LIMIT $start, $limit";
2033
        }
2034
        $result = Database::query($sql);
2035
        $works = array();
2036
2037
        if ($getCount) {
2038
            $work = Database::fetch_array($result, 'ASSOC');
2039
            return $work['count'];
2040
        }
2041
2042
        $url = api_get_path(WEB_CODE_PATH).'work/';
2043
        $unoconv = api_get_configuration_value('unoconv.binaries');
2044
        $loadingText = addslashes(get_lang('Loading'));
2045
        $uploadedText = addslashes(get_lang('Uploaded'));
2046
        $failsUploadText = addslashes(get_lang('UplNoFileUploaded'));
2047
        $failsUploadIcon = Display::return_icon(
2048
            'closed-circle.png',
2049
            '',
2050
            [],
2051
            ICON_SIZE_TINY
2052
        );
2053
        $saveIcon = Display::return_icon(
2054
            'save.png',
2055
            get_lang('Save'),
2056
            array(),
2057
            ICON_SIZE_SMALL
2058
        );
2059
2060
        $correctionIcon = Display::return_icon(
2061
            'check-circle.png',
2062
            get_lang('Correction'),
2063
            null,
2064
            ICON_SIZE_SMALL
2065
        );
2066
2067
        $correctionIconSmall = Display::return_icon(
2068
            'check-circle.png',
2069
            get_lang('Correction'),
2070
            null,
2071
            ICON_SIZE_TINY
2072
        );
2073
2074
        $rateIcon = Display::return_icon(
2075
            'rate_work.png',
2076
            get_lang('CorrectAndRate'),
2077
            array(),
2078
            ICON_SIZE_SMALL
2079
        );
2080
2081
        while ($work = Database::fetch_array($result, 'ASSOC')) {
2082
            $item_id = $work['id'];
2083
            // Get the author ID for that document from the item_property table
2084
            $is_author = false;
2085
            $can_read = false;
2086
            $owner_id = $work['user_id'];
2087
2088
            /* Because a bug found when saving items using the api_item_property_update()
2089
               the field $item_property_data['insert_user_id'] is not reliable. */
2090
            if (!$is_allowed_to_edit && $owner_id == api_get_user_id()) {
2091
                $is_author = true;
2092
            }
2093
2094
            if ($course_info['show_score'] == 0) {
2095
                $can_read = true;
2096
            }
2097
2098
            $qualification_exists = false;
2099 View Code Duplication
            if (!empty($work_data['qualification']) &&
2100
                intval($work_data['qualification']) > 0
2101
            ) {
2102
                $qualification_exists = true;
2103
            }
2104
2105
            $qualification_string = '';
2106
            if ($qualification_exists) {
2107
                if ($work['qualification'] == '') {
2108
                    $qualification_string = Display::label('-');
2109
                } else {
2110
                    $qualification_string = formatWorkScore($work['qualification'], $work_data['qualification']);
2111
                }
2112
            }
2113
2114
            $work['qualification_score'] = $work['qualification'];
2115
            $add_string = '';
2116
            $time_expires = '';
2117
            if (!empty($work_assignment['expires_on'])) {
2118
                $time_expires = api_strtotime(
2119
                    $work_assignment['expires_on'],
2120
                    'UTC'
2121
                );
2122
            }
2123
2124
            if (!empty($work_assignment['expires_on']) &&
2125
                !empty($time_expires) && ($time_expires < api_strtotime($work['sent_date'], 'UTC'))) {
2126
                $add_string = Display::label(get_lang('Expired'), 'important').' - ';
2127
            }
2128
2129
            if (($can_read && $work['accepted'] == '1') ||
2130
                ($is_author && in_array($work['accepted'], array('1', '0'))) ||
2131
                ($is_allowed_to_edit || api_is_drh())
2132
            ) {
2133
                // Firstname, lastname, username
2134
                $work['fullname'] = Display::div(
2135
                    api_get_person_name($work['firstname'], $work['lastname']),
2136
                    ['class' => 'work-name']
2137
                );
2138
                // Title
2139
                $work['title_clean'] = $work['title'];
2140
                $work['title'] = Security::remove_XSS($work['title']);
2141
                if (strlen($work['title']) > 30) {
2142
                    $short_title = substr($work['title'], 0, 27).'...';
2143
                    $work['title'] = Display::span($short_title, array('class' => 'work-title', 'title' => $work['title']));
2144
                } else {
2145
                    $work['title'] = Display::div($work['title'], array('class' => 'work-title'));
2146
                }
2147
2148
                // Type.
2149
                $work['type'] = DocumentManager::build_document_icon_tag('file', $work['url']);
2150
2151
                // File name.
2152
                $link_to_download = null;
2153
                // If URL is present then there's a file to download keep BC.
2154
                if ($work['contains_file'] || !empty($work['url'])) {
2155
                    $link_to_download = '<a href="'.$url.'download.php?id='.$item_id.'&'.api_get_cidreq().'">'.$saveIcon.'</a> ';
2156
                }
2157
2158
                $feedback = '';
2159
                $count = getWorkCommentCount($item_id, $course_info);
2160
                if (!is_null($count) && !empty($count)) {
2161
                    if ($qualification_exists) {
2162
                        $feedback .= ' ';
2163
                    }
2164
                    $feedback .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2165
                    $count.' '.Display::returnFontAwesomeIcon('comments-o').'</a> ';
2166
                }
2167
2168
                $correction = '';
2169
                $hasCorrection = '';
2170 View Code Duplication
                if (!empty($work['url_correction'])) {
2171
                    $hasCorrection = Display::url(
2172
                        $correctionIcon,
2173
                        api_get_path(WEB_CODE_PATH).'work/download.php?id='.$item_id.'&'.api_get_cidreq().'&correction=1'
2174
                    );
2175
                }
2176
2177
                if ($qualification_exists) {
2178
                    $work['qualification'] = $qualification_string.$feedback;
2179
                } else {
2180
                    $work['qualification'] = $qualification_string.$feedback.$hasCorrection;
2181
                }
2182
2183
                $work['qualification_only'] = $qualification_string;
2184
2185
                // Date.
2186
                $work_date = api_get_local_time($work['sent_date']);
2187
                $date = date_to_str_ago($work['sent_date']).' '.$work_date;
2188
                $work['formatted_date'] = $work_date.' '.$add_string;
2189
                $work['sent_date_from_db'] = $work['sent_date'];
2190
                $work['sent_date'] = '<div class="work-date" title="'.$date.'">'.$add_string.' '.Display::dateToStringAgoAndLongDate($work['sent_date']).'</div>';
2191
                $work['status'] = $hasCorrection;
2192
                $work['has_correction'] = $hasCorrection;
2193
2194
                // Actions.
2195
                $action = '';
2196
                if (api_is_allowed_to_edit()) {
2197
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.$rateIcon.'</a> ';
2198
2199 View Code Duplication
                    if ($unoconv && empty($work['contains_file'])) {
2200
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=export_to_doc&item_id='.$item_id.'" title="'.get_lang('ExportToDoc').'" >'.
2201
                            Display::return_icon('export_doc.png', get_lang('ExportToDoc'), array(), ICON_SIZE_SMALL).'</a> ';
2202
                    }
2203
2204
                    $alreadyUploaded = '';
2205
                    if (!empty($work['url_correction'])) {
2206
                        $alreadyUploaded = '<br />'.$work['title_correction'].' '.$correctionIconSmall;
2207
                    }
2208
2209
                    $correction = '
2210
                        <form
2211
                        id="file_upload_'.$item_id.'"
2212
                        class="work_correction_file_upload file_upload_small fileinput-button"
2213
                        action="'.api_get_path(WEB_AJAX_PATH).'work.ajax.php?'.api_get_cidreq().'&a=upload_correction_file&item_id='.$item_id.'" method="POST" enctype="multipart/form-data"
2214
                        >
2215
                        <div id="progress_'.$item_id.'" class="text-center button-load">
2216
                            '.addslashes(get_lang('ClickOrDropOneFileHere')).'
2217
                            '.Display::return_icon('upload_file.png', get_lang('Correction'), [], ICON_SIZE_TINY).'
2218
                            '.$alreadyUploaded.'
2219
                        </div>
2220
                        <input id="file_'.$item_id.'" type="file" name="file" class="" multiple>
2221
                        </form>
2222
                    ';
2223
2224
                    $correction .= "<script>
2225
                    $(document).ready(function() {
2226
                        $('.work_correction_file_upload').each(function () {
2227
                            $(this).fileupload({
2228
                                dropZone: $(this)
2229
                            });
2230
                        });
2231
                        $('#file_upload_".$item_id."').fileupload({
2232
                            add: function (e, data) {
2233
                                $('#progress_$item_id').html();
2234
                                //$('#file_$item_id').remove();
2235
                                data.context = $('#progress_$item_id').html('$loadingText <br /> <em class=\"fa fa-spinner fa-pulse fa-fw\"></em>');
2236
                                data.submit();
2237
                                $(this).removeClass('hover');
2238
                            },
2239
                            dragover: function (e, data) {
2240
                                $(this).addClass('hover');
2241
                            },
2242
                            done: function (e, data) {
2243
                                if (data._response.result.name) {
2244
                                    $('#progress_$item_id').html('$uploadedText '+data._response.result.result+'<br />'+data._response.result.name);
2245
                                } else {
2246
                                    $('#progress_$item_id').html('$failsUploadText $failsUploadIcon');
2247
                                }
2248
                                $(this).removeClass('hover');
2249
                            }
2250
                        });
2251
                        $('#file_upload_".$item_id."').on('dragleave', function (e) {
2252
                            // dragleave callback implementation
2253
                            $(this).removeClass('hover');
2254
                        });
2255
                    });
2256
                    </script>";
2257
2258
                    if ($locked) {
2259
                        if ($qualification_exists) {
2260
                            $action .= Display::return_icon('edit_na.png', get_lang('CorrectAndRate'), array(), ICON_SIZE_SMALL);
2261
                        } else {
2262
                            $action .= Display::return_icon('edit_na.png', get_lang('Comment'), array(), ICON_SIZE_SMALL);
2263
                        }
2264 View Code Duplication
                    } else {
2265
                        if ($qualification_exists) {
2266
                            $action .= '<a href="'.$url.'edit.php?'.api_get_cidreq().'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Edit').'"  >'.
2267
                                Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL).'</a>';
2268
                        } else {
2269
                            $action .= '<a href="'.$url.'edit.php?'.api_get_cidreq().'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Modify').'">'.
2270
                                Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL).'</a>';
2271
                        }
2272
                    }
2273
2274 View Code Duplication
                    if ($work['contains_file']) {
2275
                        if ($locked) {
2276
                            $action .= Display::return_icon(
2277
                                'move_na.png',
2278
                                get_lang('Move'),
2279
                                array(),
2280
                                ICON_SIZE_SMALL
2281
                            );
2282
                        } else {
2283
                            $action .= '<a href="'.$url.'work.php?'.api_get_cidreq().'&action=move&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Move').'">'.
2284
                                Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL).'</a>';
2285
                        }
2286
                    }
2287
2288 View Code Duplication
                    if ($work['accepted'] == '1') {
2289
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=make_invisible&item_id='.$item_id.'" title="'.get_lang('Invisible').'" >'.
2290
                            Display::return_icon('visible.png', get_lang('Invisible'), array(), ICON_SIZE_SMALL).'</a>';
2291
                    } else {
2292
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=make_visible&item_id='.$item_id.'" title="'.get_lang('Visible').'" >'.
2293
                            Display::return_icon('invisible.png', get_lang('Visible'), array(), ICON_SIZE_SMALL).'</a> ';
2294
                    }
2295
2296
                    if ($locked) {
2297
                        $action .= Display::return_icon('delete_na.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2298
                    } else {
2299
                        $action .= '<a href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=delete&item_id='.$item_id.'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'" >'.
2300
                            Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2301
                    }
2302
                } elseif ($is_author && (empty($work['qualificator_id']) || $work['qualificator_id'] == 0)) {
2303
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2304
                        Display::return_icon('default.png', get_lang('View'), array(), ICON_SIZE_SMALL).'</a>';
2305
2306
                    if (api_get_course_setting('student_delete_own_publication') == 1) {
2307 View Code Duplication
                        if (api_is_allowed_to_session_edit(false, true)) {
2308
                            $action .= '<a href="'.$url.'edit.php?'.api_get_cidreq().'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Modify').'">'.
2309
                                Display::return_icon('edit.png', get_lang('Comment'), array(), ICON_SIZE_SMALL).'</a>';
2310
                        }
2311
                        $action .= ' <a href="'.$url.'work_list.php?'.api_get_cidreq().'&action=delete&item_id='.$item_id.'&id='.$work['parent_id'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'"  >'.
2312
                            Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2313
                    }
2314
                } else {
2315
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2316
                        Display::return_icon('default.png', get_lang('View'), array(), ICON_SIZE_SMALL).'</a>';
2317
                }
2318
2319
                // Status.
2320 View Code Duplication
                if (empty($work['qualificator_id'])) {
2321
                    $qualificator_id = Display::label(get_lang('NotRevised'), 'warning');
2322
                } else {
2323
                    $qualificator_id = Display::label(get_lang('Revised'), 'success');
2324
                }
2325
                $work['qualificator_id'] = $qualificator_id.' '.$hasCorrection;
2326
                $work['actions'] = '<div class="work-action">'.$send_to.$link_to_download.$action.'</div>';
0 ignored issues
show
Bug introduced by
The variable $send_to does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
2327
                $work['correction'] = $correction;
2328
                $works[] = $work;
2329
            }
2330
        }
2331
2332
        return $works;
2333
    }
2334
}
2335
2336
/**
2337
 * Send reminder to users who have not given the task
2338
 *
2339
 * @param int
2340
 * @return array
2341
 * @author cvargas [email protected] cfasanando, [email protected]
2342
 */
2343
function send_reminder_users_without_publication($task_data)
2344
{
2345
    $_course = api_get_course_info();
2346
    $task_id = $task_data['id'];
2347
    $task_title = !empty($task_data['title']) ? $task_data['title'] : basename($task_data['url']);
2348
    $subject = '['.api_get_setting('siteName').'] ';
2349
2350
    // The body can be as long as you wish, and any combination of text and variables
2351
    $content = get_lang('ReminderToSubmitPendingTask')."\n".get_lang('CourseName').' : '.$_course['name']."\n";
2352
    $content .= get_lang('WorkName').' : '.$task_title."\n";
2353
    $list_users = get_list_users_without_publication($task_id);
2354
    $mails_sent_to = array();
2355
    foreach ($list_users as $user) {
2356
        $name_user = api_get_person_name($user[1], $user[0], null, PERSON_NAME_EMAIL_ADDRESS);
2357
        $dear_line = get_lang('Dear')." ".api_get_person_name($user[1], $user[0]).", \n\n";
2358
        $body      = $dear_line.$content;
2359
        MessageManager::send_message($user[3], $subject, $body);
2360
        $mails_sent_to[] = $name_user;
2361
    }
2362
    return $mails_sent_to;
2363
}
2364
2365
/**
2366
 * @param int $courseId The course ID
2367
 * @param int $workId The work ID
2368
 * @param int $sessionId Optional. The session ID
2369
 */
2370
function sendEmailToDrhOnHomeworkCreation($courseId, $workId, $sessionId = 0)
2371
{
2372
    $courseInfo = api_get_course_info_by_id($courseId);
2373
    $assignment = get_work_assignment_by_id($workId, $courseId);
2374
    $work = get_work_data_by_id($workId, $courseId, $sessionId);
2375
    $workInfo = array_merge($assignment, $work);
2376
2377 View Code Duplication
    if (empty($session_id)) {
0 ignored issues
show
Bug introduced by
The variable $session_id seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
2378
        $students = CourseManager::get_student_list_from_course_code($courseInfo['code']);
2379
    } else {
2380
        $students = CourseManager::get_student_list_from_course_code($courseInfo['code'], true, $sessionId);
2381
    }
2382
2383
    $bodyView = new Template(null, false, false, false, false, false);
2384
2385
    foreach ($students as $student) {
2386
        $student['complete_name'] = api_get_person_name($student["firstname"], $student["lastname"]);
2387
        $hrms = UserManager::getDrhListFromUser($student['id']);
2388
2389
        foreach ($hrms as $hrm) {
2390
            $hrmName = api_get_person_name($hrm['firstname'], $hrm['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
2391
2392
            $bodyView->assign('hrm_name', $hrmName);
2393
            $bodyView->assign('student', $student);
2394
            $bodyView->assign('course', $courseInfo);
2395
            $bodyView->assign('course_link', api_get_course_url($courseInfo['code'], $sessionId));
2396
            $bodyView->assign('work', $workInfo);
2397
2398
            $bodyTemplate = $bodyView->get_template('mail/new_work_alert_hrm.tpl');
2399
2400
            MessageManager::send_message(
2401
                $hrm['id'],
2402
                sprintf(
2403
                    get_lang('StudentXHasBeenAssignedNewWorkInCourseY'),
2404
                    $student['firstname'],
2405
                    $courseInfo['title']
2406
                ),
2407
                $bodyView->fetch($bodyTemplate)
2408
            );
2409
        }
2410
    }
2411
}
2412
2413
/**
2414
 * Sends an email to the students of a course when a homework is created
2415
 *
2416
 * @param int $courseId course_id
2417
 * @param int $sessionId session_id
2418
 * @param int $workId work_id
2419
 *
2420
 *
2421
 * @author Guillaume Viguier <[email protected]>
2422
 * @author Julio Montoya <[email protected]> Adding session support - 2011
2423
 */
2424
function sendEmailToStudentsOnHomeworkCreation($courseId, $sessionId = 0, $workId)
2425
{
2426
    $courseInfo = api_get_course_info_by_id($courseId);
2427
    $courseCode = $courseInfo['code'];
2428
    // Get the students of the course
2429 View Code Duplication
    if (empty($session_id)) {
0 ignored issues
show
Bug introduced by
The variable $session_id seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
2430
        $students = CourseManager::get_student_list_from_course_code($courseCode);
2431
    } else {
2432
        $students = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionId);
2433
    }
2434
    $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('HomeworkCreated');
2435
    $currentUser = api_get_user_info(api_get_user_id());
2436
    if (!empty($students)) {
2437
        foreach ($students as $student) {
2438
            $user_info = api_get_user_info($student["user_id"]);
2439
            if (!empty($user_info["mail"])) {
2440
                $name_user = api_get_person_name(
2441
                    $user_info["firstname"],
2442
                    $user_info["lastname"],
2443
                    null,
2444
                    PERSON_NAME_EMAIL_ADDRESS
2445
                );
2446
                $link = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq().'&id='.$workId;
2447
                $emailbody = get_lang('Dear')." ".$name_user.",\n\n";
2448
                $emailbody .= get_lang('HomeworkHasBeenCreatedForTheCourse')." ".$courseCode.". "."\n\n".
2449
                    '<a href="'.$link.'">'.get_lang('PleaseCheckHomeworkPage').'</a>';
2450
                $emailbody .= "\n\n".api_get_person_name($currentUser["firstname"], $currentUser["lastname"]);
2451
2452
                $additionalParameters = array(
2453
                    'smsType' => SmsPlugin::ASSIGNMENT_BEEN_CREATED_COURSE,
2454
                    'userId' => $student["user_id"],
2455
                    'courseTitle' => $courseCode,
2456
                    'link' => $link
2457
                );
2458
2459
                api_mail_html(
2460
                    $name_user,
2461
                    $user_info["mail"],
2462
                    $emailsubject,
2463
                    $emailbody,
2464
                    api_get_person_name(
2465
                        $currentUser["firstname"],
2466
                        $currentUser["lastname"],
2467
                        null,
2468
                        PERSON_NAME_EMAIL_ADDRESS
2469
                    ),
2470
                    $currentUser["mail"],
2471
                    null,
2472
                    null,
2473
                    null,
2474
                    $additionalParameters
2475
                );
2476
            }
2477
        }
2478
    }
2479
}
2480
2481
/**
2482
 * @param string $url
2483
 * @return bool
2484
 */
2485
function is_work_exist_by_url($url)
2486
{
2487
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2488
    $url = Database::escape_string($url);
2489
    $sql = "SELECT id FROM $work_table WHERE url='$url'";
2490
    $result = Database::query($sql);
2491
    if (Database::num_rows($result) > 0) {
2492
        $row = Database::fetch_row($result);
2493
        if (empty($row)) {
2494
            return false;
2495
        } else {
2496
            return true;
2497
        }
2498
    } else {
2499
        return false;
2500
    }
2501
}
2502
2503
/**
2504
 * Check if a user is the author of a work document.
2505
 * @param int $itemId
2506
 * @param int $userId
2507
 * @param int $courseId
2508
 * @param int $sessionId
2509
 * @return bool
2510
 */
2511
function user_is_author($itemId, $userId = null, $courseId = null, $sessionId = null)
2512
{
2513
    if (empty($itemId)) {
2514
        return false;
2515
    }
2516
2517
    if (empty($userId)) {
2518
        $userId = api_get_user_id();
2519
    }
2520
2521
    $isAuthor = false;
2522
    $is_allowed_to_edit = api_is_allowed_to_edit();
2523
2524
    if ($is_allowed_to_edit) {
2525
        $isAuthor = true;
2526
    } else {
2527
2528
        if (empty($courseId)) {
2529
            $courseId = api_get_course_int_id();
2530
        }
2531
        if (empty($sessionId)) {
2532
            $sessionId = api_get_session_id();
2533
        }
2534
2535
        $data = api_get_item_property_info($courseId, 'work', $itemId, $sessionId);
2536
        if ($data['insert_user_id'] == $userId) {
2537
            $isAuthor = true;
2538
        }
2539
2540
        $workData = get_work_data_by_id($itemId);
2541
        if ($workData['user_id'] == $userId) {
2542
            $isAuthor = true;
2543
        }
2544
    }
2545
2546
    if (!$isAuthor) {
2547
        return false;
2548
    }
2549
2550
    return $isAuthor;
2551
}
2552
2553
/**
2554
 * Get list of users who have not given the task
2555
 * @param int
2556
 * @param int
2557
 * @return array
2558
 * @author cvargas
2559
 * @author Julio Montoya <[email protected]> Fixing query
2560
 */
2561
function get_list_users_without_publication($task_id, $studentId = null)
2562
{
2563
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2564
    $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2565
    $table_user = Database::get_main_table(TABLE_MAIN_USER);
2566
    $session_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2567
2568
    $users = getAllUserToWork($task_id, api_get_course_int_id());
2569
    $users = array_column($users, 'user_id');
2570
2571
    // Condition for the session
2572
    $session_id = api_get_session_id();
2573
    $course_id = api_get_course_int_id();
2574
    $task_id = intval($task_id);
2575
    $sessionCondition = api_get_session_condition($session_id);
2576
2577
    if ($session_id == 0) {
2578
        $sql = "SELECT user_id as id FROM $work_table
2579
                WHERE
2580
                    c_id = $course_id AND
2581
                    parent_id = '$task_id' AND
2582
                    active IN (0, 1)";
2583
    } else {
2584
        $sql = "SELECT user_id as id FROM $work_table
2585
                WHERE
2586
                    c_id = $course_id AND
2587
                    parent_id = '$task_id' $sessionCondition AND
2588
                    active IN (0, 1)";
2589
    }
2590
2591
    $result = Database::query($sql);
2592
    $users_with_tasks = array();
2593
    while ($row = Database::fetch_array($result)) {
2594
        $users_with_tasks[] = $row['id'];
2595
    }
2596
2597
    if ($session_id == 0) {
2598
        $sql_users = "SELECT cu.user_id, u.lastname, u.firstname, u.email
2599
                      FROM $table_course_user AS cu, $table_user AS u
2600
                      WHERE u.status != 1 and cu.c_id='".$course_id."' AND u.user_id = cu.user_id";
2601
    } else {
2602
        $sql_users = "SELECT cu.user_id, u.lastname, u.firstname, u.email
2603
                      FROM $session_course_rel_user AS cu, $table_user AS u
2604
                      WHERE
2605
                        u.status != 1 AND
2606
                        cu.c_id='".$course_id."' AND
2607
                        u.user_id = cu.user_id AND
2608
                        cu.session_id = '".$session_id."'";
2609
    }
2610
2611
    if (!empty($studentId)) {
2612
        $sql_users .= " AND u.user_id = ".intval($studentId);
2613
    }
2614
2615
    $group_id = api_get_group_id();
2616
    $new_group_user_list = array();
2617
2618 View Code Duplication
    if ($group_id) {
2619
        $groupInfo = GroupManager::get_group_properties($group_id);
2620
        $group_user_list = GroupManager::get_subscribed_users($groupInfo);
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group_properties($group_id) on line 2619 can also be of type null; however, GroupManager::get_subscribed_users() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2621
        if (!empty($group_user_list)) {
2622
            foreach ($group_user_list as $group_user) {
2623
                $new_group_user_list[] = $group_user['user_id'];
2624
            }
2625
        }
2626
    }
2627
2628
    $result_users = Database::query($sql_users);
2629
    $users_without_tasks = array();
2630
    while ($rowUsers = Database::fetch_array($result_users)) {
2631
        $userId = $rowUsers['user_id'];
2632
        if (in_array($userId, $users_with_tasks)) {
2633
            continue;
2634
        }
2635
2636
        if ($group_id && !in_array($userId, $new_group_user_list)) {
2637
            continue;
2638
        }
2639
2640
        if (!empty($users)) {
2641
            if (!in_array($userId, $users)) {
2642
                continue;
2643
            }
2644
        }
2645
2646
        $row_users = [];
2647
        $row_users[0] = $rowUsers['lastname'];
2648
        $row_users[1] = $rowUsers['firstname'];
2649
        $row_users[2] = Display::encrypted_mailto_link($rowUsers['email']);
2650
        $row_users[3] = $userId;
2651
        $users_without_tasks[] = $row_users;
2652
    }
2653
2654
    return $users_without_tasks;
2655
}
2656
2657
/**
2658
 * Display list of users who have not given the task
2659
 *
2660
 * @param int task id
2661
 * @param int $studentId
2662
 * @return array
2663
 * @author cvargas [email protected] cfasanando, [email protected]
2664
 * @author Julio Montoya <[email protected]> Fixes
2665
 */
2666
function display_list_users_without_publication($task_id, $studentId = null)
2667
{
2668
    global $origin;
2669
    $table_header[] = array(get_lang('LastName'), true);
2670
    $table_header[] = array(get_lang('FirstName'), true);
2671
    $table_header[] = array(get_lang('Email'), true);
2672
2673
    $data = get_list_users_without_publication($task_id);
2674
2675
    $sorting_options = array();
2676
    $sorting_options['column'] = 1;
2677
    $paging_options = array();
2678
    $my_params = array();
2679
2680
    if (isset($_GET['edit_dir'])) {
2681
        $my_params['edit_dir'] = Security::remove_XSS($_GET['edit_dir']);
2682
    }
2683
    if (isset($_GET['list'])) {
2684
        $my_params['list'] = Security::remove_XSS($_GET['list']);
2685
    }
2686
    $my_params['origin'] = $origin;
2687
    $my_params['id'] = intval($_GET['id']);
2688
2689
    //$column_show
2690
    $column_show[] = 1;
2691
    $column_show[] = 1;
2692
    $column_show[] = 1;
2693
    Display::display_sortable_config_table(
2694
        'work',
2695
        $table_header,
2696
        $data,
2697
        $sorting_options,
2698
        $paging_options,
2699
        $my_params,
2700
        $column_show
2701
    );
2702
}
2703
2704
/**
2705
 * @param int $documentId
2706
 * @param int $workId
2707
 * @param int $courseId
2708
 */
2709 View Code Duplication
function addDocumentToWork($documentId, $workId, $courseId)
2710
{
2711
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2712
    $params = array(
2713
        'document_id' => $documentId,
2714
        'work_id' => $workId,
2715
        'c_id' => $courseId
2716
    );
2717
    Database::insert($table, $params);
2718
}
2719
2720
/**
2721
 * @param int $documentId
2722
 * @param int $workId
2723
 * @param int $courseId
2724
 * @return array
2725
 */
2726 View Code Duplication
function getDocumentToWork($documentId, $workId, $courseId)
2727
{
2728
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2729
    $params = array(
2730
        'document_id = ? and work_id = ? and c_id = ?' => array($documentId, $workId, $courseId)
2731
    );
2732
    return Database::select('*', $table, array('where' => $params));
2733
}
2734
2735
/**
2736
 * @param int $documentId
2737
 * @param int $workId
2738
 * @param int $courseId
2739
 * @param int $sessionId
2740
 * @param int $userId
2741
 * @param int $active
2742
 * @return array
2743
 */
2744
function getDocumentToWorkPerUser($documentId, $workId, $courseId, $sessionId, $userId, $active = 1)
2745
{
2746
    $workRel = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2747
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2748
2749
    $documentId = intval($documentId);
2750
    $workId = intval($workId);
2751
    $courseId = intval($courseId);
2752
    $userId = intval($userId);
2753
    $sessionId = intval($sessionId);
2754
    $active = intval($active);
2755
    $sessionCondition = api_get_session_condition($sessionId);
2756
2757
    $sql = "SELECT w.* FROM $work w INNER JOIN $workRel rel ON (w.parent_id = rel.work_id)
2758
            WHERE
2759
                w.document_id = $documentId AND
2760
                w.parent_id = $workId AND
2761
                w.c_id = $courseId
2762
                $sessionCondition AND
2763
                user_id = $userId AND
2764
                active = $active
2765
            ";
2766
2767
    $result = Database::query($sql);
2768
    $workInfo = array();
2769
    if (Database::num_rows($result)) {
2770
        $workInfo = Database::fetch_array($result, 'ASSOC');
2771
    }
2772
    return $workInfo;
2773
}
2774
2775
/**
2776
 *
2777
 * @param int $workId
2778
 * @param int $courseId
2779
 * @return array
2780
 */
2781 View Code Duplication
function getAllDocumentToWork($workId, $courseId)
2782
{
2783
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2784
    $params = array(
2785
        'work_id = ? and c_id = ?' => array($workId, $courseId)
2786
    );
2787
    return Database::select('*', $table, array('where' => $params));
2788
}
2789
2790
/**
2791
 * @param int $documentId
2792
 * @param int $workId
2793
 * @param int $courseId
2794
 */
2795 View Code Duplication
function deleteDocumentToWork($documentId, $workId, $courseId)
2796
{
2797
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2798
    $params = array(
2799
        'document_id = ? and work_id = ? and c_id = ?' => array($documentId, $workId, $courseId)
2800
    );
2801
    Database::delete($table, $params);
2802
}
2803
2804
/**
2805
 * @param int $userId
2806
 * @param int $workId
2807
 * @param int $courseId
2808
 */
2809 View Code Duplication
function addUserToWork($userId, $workId, $courseId)
2810
{
2811
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2812
    $params = array(
2813
        'user_id' => $userId,
2814
        'work_id' => $workId,
2815
        'c_id' => $courseId
2816
    );
2817
    Database::insert($table, $params);
2818
}
2819
2820
/**
2821
 * @param int $userId
2822
 * @param int $workId
2823
 * @param int $courseId
2824
 * @return array
2825
 */
2826 View Code Duplication
function getUserToWork($userId, $workId, $courseId)
2827
{
2828
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2829
    $params = array(
2830
        'user_id = ? and work_id = ? and c_id = ?' => array($userId, $workId, $courseId)
2831
    );
2832
    return Database::select('*', $table, array('where' => $params));
2833
}
2834
2835
/**
2836
 * @param int $workId
2837
 * @param int $courseId
2838
 * @param bool $getCount
2839
 * @return array|int
2840
 */
2841
function getAllUserToWork($workId, $courseId, $getCount = false)
2842
{
2843
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2844
    $params = array(
2845
        'work_id = ? and c_id = ?' => array($workId, $courseId)
2846
    );
2847
    if ($getCount) {
2848
        $count = 0;
2849
        $result = Database::select(
2850
            'count(user_id) as count',
2851
            $table,
2852
            array('where' => $params),
2853
            'simple'
2854
        );
2855
        if (!empty($result)) {
2856
            $count = intval($result['count']);
2857
        }
2858
        return $count;
2859
    } else {
2860
        return Database::select('*', $table, array('where' => $params));
2861
    }
2862
}
2863
2864
/**
2865
 * @param int $userId
2866
 * @param int $workId
2867
 * @param int $courseId
2868
 */
2869 View Code Duplication
function deleteUserToWork($userId, $workId, $courseId)
2870
{
2871
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2872
    $params = array(
2873
        'user_id = ? and work_id = ? and c_id = ?' => array($userId, $workId, $courseId)
2874
    );
2875
    Database::delete($table, $params);
2876
}
2877
2878
/**
2879
 * @param int $userId
2880
 * @param int $workId
2881
 * @param int $courseId
2882
 * @return bool
2883
 */
2884
function userIsSubscribedToWork($userId, $workId, $courseId)
2885
{
2886
    $subscribedUsers = getAllUserToWork($workId, $courseId);
2887
2888
    if (empty($subscribedUsers)) {
2889
        return true;
2890
    } else {
2891
        $subscribedUsersList = array();
2892
        foreach ($subscribedUsers as $item) {
0 ignored issues
show
Bug introduced by
The expression $subscribedUsers of type integer|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2893
            $subscribedUsersList[] = $item['user_id'];
2894
        }
2895
        if (in_array($userId, $subscribedUsersList)) {
2896
            return true;
2897
        }
2898
    }
2899
    return false;
2900
}
2901
2902
/**
2903
 * Get the list of students that have to submit their work
2904
 * @param integer $workId The internal ID of the assignment
2905
 * @param integer $courseId The course ID
2906
 * @param integer $groupId The group ID, if any
2907
 * @param integer $sessionId The session ID, if any
2908
 * @param bool $getCount Whether we want just the amount or the full result
2909
 * @return array|int An integer (if we just asked for the count) or an array of users
2910
 */
2911
function getStudentSubscribedToWork(
2912
    $workId,
2913
    $courseId,
2914
    $groupId = null,
2915
    $sessionId = null,
2916
    $getCount = false
2917
) {
2918
    $usersInWork = null;
2919
    $usersInCourse = null;
2920
2921
    if (empty($groupId)) {
2922
        $courseInfo = api_get_course_info_by_id($courseId);
2923
        $status = STUDENT;
2924
        if (!empty($sessionId)) {
2925
            $status = 0;
2926
        }
2927
        $usersInCourse = CourseManager::get_user_list_from_course_code(
2928
            $courseInfo['code'],
2929
            $sessionId,
2930
            null,
2931
            null,
2932
            $status,
2933
            $getCount
2934
        );
2935
    } else {
2936
        $usersInCourse = GroupManager::get_users(
2937
            $groupId,
2938
            false,
2939
            null,
2940
            null,
2941
            $getCount,
2942
            $courseId
2943
        );
2944
    }
2945
2946
    $usersInWork = getAllUserToWork($workId, $courseId, $getCount);
2947
2948
    if (empty($usersInWork)) {
2949
        return $usersInCourse;
2950
    } else {
2951
        return $usersInWork;
2952
    }
2953
}
2954
2955
/**
2956
 * @param int $userId
2957
 * @param int $workId
2958
 * @param int $courseId
2959
 * @return bool
2960
 */
2961
function allowOnlySubscribedUser($userId, $workId, $courseId)
2962
{
2963
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
2964
        return true;
2965
    }
2966
2967
    if (userIsSubscribedToWork($userId, $workId, $courseId) == false) {
2968
        api_not_allowed(true);
2969
    }
2970
}
2971
2972
/**
2973
 * @param int $workId
2974
 * @param array $courseInfo
2975
 * @param int $documentId
2976
 * @return array
2977
 */
2978
function getDocumentTemplateFromWork($workId, $courseInfo, $documentId)
2979
{
2980
    $documents = getAllDocumentToWork($workId, $courseInfo['real_id']);
2981
    if (!empty($documents)) {
2982
        foreach ($documents as $doc) {
2983
            if ($documentId != $doc['document_id']) {
2984
                continue;
2985
            }
2986
            $docData = DocumentManager::get_document_data_by_id($doc['document_id'], $courseInfo['code']);
2987
            $fileInfo = pathinfo($docData['path']);
2988
            if ($fileInfo['extension'] == 'html') {
2989
                if (file_exists($docData['absolute_path']) && is_file($docData['absolute_path'])) {
2990
                    $docData['file_content'] = file_get_contents($docData['absolute_path']);
2991
                    return $docData;
2992
                }
2993
            }
2994
        }
2995
    }
2996
    return array();
2997
}
2998
2999
/**
3000
 * @param int $workId
3001
 * @param array $courseInfo
3002
 * @return string
3003
 */
3004
function getAllDocumentsFromWorkToString($workId, $courseInfo)
3005
{
3006
    $documents = getAllDocumentToWork($workId, $courseInfo['real_id']);
3007
    $content = null;
3008
    if (!empty($documents)) {
3009
        $content .= '<ul class="nav nav-list well">';
3010
        $content .= '<li class="nav-header">'.get_lang('Documents').'</li>';
3011
        foreach ($documents as $doc) {
3012
            $docData = DocumentManager::get_document_data_by_id($doc['document_id'], $courseInfo['code']);
3013
            if ($docData) {
3014
                $content .= '<li><a target="_blank" href="'.$docData['url'].'">'.$docData['title'].'</a></li>';
3015
            }
3016
        }
3017
        $content .= '</ul><br />';
3018
    }
3019
    return $content;
3020
}
3021
3022
/**
3023
 * Returns fck editor toolbar
3024
 * @return array
3025
 */
3026
function getWorkDescriptionToolbar()
3027
{
3028
    return array(
3029
        'ToolbarStartExpanded' => 'true',
3030
        'ToolbarSet' => 'Work',
3031
        'Width' => '100%',
3032
        'Height' => '400'
3033
    );
3034
}
3035
3036
/**
3037
 * @param array $work
3038
 * @return array
3039
 */
3040
function getWorkComments($work)
3041
{
3042
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3043
    $userTable = Database::get_main_table(TABLE_MAIN_USER);
3044
3045
    $courseId = intval($work['c_id']);
3046
    $workId = intval($work['id']);
3047
3048
    if (empty($courseId) || empty($workId)) {
3049
        return array();
3050
    }
3051
3052
    $sql = "SELECT
3053
                c.id,
3054
                c.user_id
3055
            FROM $commentTable c
3056
            INNER JOIN $userTable u
3057
            ON (u.id = c.user_id)
3058
            WHERE c_id = $courseId AND work_id = $workId
3059
            ORDER BY sent_at
3060
            ";
3061
    $result = Database::query($sql);
3062
    $comments = Database::store_result($result, 'ASSOC');
3063
    if (!empty($comments)) {
3064
        foreach ($comments as &$comment) {
3065
            $userInfo = api_get_user_info($comment['user_id']);
3066
            $comment['picture'] = $userInfo['avatar'];
3067
            $comment['complete_name'] = $userInfo['complete_name_with_username'];
3068
            $commentInfo = getWorkComment($comment['id']);
3069
            if (!empty($commentInfo)) {
3070
                $comment = array_merge($comment, $commentInfo);
3071
            }
3072
        }
3073
    }
3074
    return $comments;
3075
}
3076
3077
/**
3078
 * Get total score from a work list
3079
 * @param $workList
3080
 * @return int|null
3081
 */
3082
function getTotalWorkScore($workList)
3083
{
3084
    $count = 0;
3085
    foreach ($workList as $data) {
3086
        $count += $data['qualification_score'];
3087
    }
3088
    return $count;
3089
}
3090
3091
3092
/**
3093
 * Get comment count from a work list (docs sent by students)
3094
 * @param array $workList
3095
 * @param array $courseInfo
3096
 * @return int|null
3097
 */
3098
function getTotalWorkComment($workList, $courseInfo = array())
3099
{
3100
    if (empty($courseInfo)) {
3101
        $courseInfo = api_get_course_info();
3102
    }
3103
3104
    $count = 0;
3105
    foreach ($workList as $data) {
3106
        $count += getWorkCommentCount($data['id'], $courseInfo);
3107
    }
3108
    return $count;
3109
}
3110
3111
/**
3112
 * Get comment count for a specific work sent by a student.
3113
 * @param int $id
3114
 * @param array $courseInfo
3115
 * @return int
3116
 */
3117 View Code Duplication
function getWorkCommentCount($id, $courseInfo = array())
3118
{
3119
    if (empty($courseInfo)) {
3120
        $courseInfo = api_get_course_info();
3121
    }
3122
3123
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3124
    $id = intval($id);
3125
3126
    $sql = "SELECT count(*) as count
3127
            FROM $commentTable
3128
            WHERE work_id = $id AND c_id = ".$courseInfo['real_id'];
3129
3130
    $result = Database::query($sql);
3131
    if (Database::num_rows($result)) {
3132
        $comment = Database::fetch_array($result);
3133
        return $comment['count'];
3134
    }
3135
3136
    return 0;
3137
}
3138
3139
/**
3140
 * Get comment count for a specific parent
3141
 * @param int $parentId
3142
 * @param array $courseInfo
3143
 * @param int $sessionId
3144
 * @return int
3145
 */
3146 View Code Duplication
function getWorkCommentCountFromParent(
3147
    $parentId,
3148
    $courseInfo = array(),
3149
    $sessionId = 0
3150
) {
3151
    if (empty($courseInfo)) {
3152
        $courseInfo = api_get_course_info();
3153
    }
3154
3155
    if (empty($sessionId)) {
3156
        $sessionId = api_get_session_id();
3157
    } else {
3158
        $sessionId = intval($sessionId);
3159
    }
3160
3161
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3162
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3163
    $parentId = intval($parentId);
3164
    $sessionCondition = api_get_session_condition($sessionId, false, false, 'w.session_id');
3165
3166
    $sql = "SELECT count(*) as count
3167
            FROM $commentTable c INNER JOIN $work w
3168
            ON c.c_id = w.c_id AND w.id = c.work_id
3169
            WHERE
3170
                $sessionCondition AND
3171
                parent_id = $parentId AND
3172
                w.c_id = ".$courseInfo['real_id'];
3173
3174
    $result = Database::query($sql);
3175
    if (Database::num_rows($result)) {
3176
        $comment = Database::fetch_array($result);
3177
        return $comment['count'];
3178
    }
3179
3180
    return 0;
3181
}
3182
3183
/**
3184
 * Get last work information from parent
3185
 * @param int $parentId
3186
 * @param array $courseInfo
3187
 * @param int $sessionId
3188
 * @return int
3189
 */
3190 View Code Duplication
function getLastWorkStudentFromParent(
3191
    $parentId,
3192
    $courseInfo = array(),
3193
    $sessionId = 0
3194
) {
3195
    if (empty($courseInfo)) {
3196
        $courseInfo = api_get_course_info();
3197
    }
3198
3199
    if (empty($sessionId)) {
3200
        $sessionId = api_get_session_id();
3201
    } else {
3202
        $sessionId = intval($sessionId);
3203
    }
3204
3205
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3206
    $sessionCondition = api_get_session_condition($sessionId, false);
3207
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3208
    $parentId = intval($parentId);
3209
3210
    $sql = "SELECT w.*
3211
            FROM $commentTable c INNER JOIN $work w
3212
            ON c.c_id = w.c_id AND w.id = c.work_id
3213
            WHERE
3214
                $sessionCondition AND
3215
                parent_id = $parentId AND
3216
                w.c_id = ".$courseInfo['real_id']."
3217
            ORDER BY w.sent_date
3218
            LIMIT 1
3219
            ";
3220
3221
    $result = Database::query($sql);
3222
    if (Database::num_rows($result)) {
3223
        $comment = Database::fetch_array($result, 'ASSOC');
3224
3225
        return $comment;
3226
    }
3227
3228
    return array();
3229
}
3230
3231
/**
3232
 * Get last work information from parent
3233
 * @param array $parentInfo
3234
 * @param array $courseInfo
3235
 * @param int $sessionId
3236
 * @return int
3237
 */
3238
function getLastWorkStudentFromParentByUser(
3239
    $userId,
3240
    $parentInfo,
3241
    $courseInfo = array(),
3242
    $sessionId = 0
3243
) {
3244
    if (empty($courseInfo)) {
3245
        $courseInfo = api_get_course_info();
3246
    }
3247
3248
    if (empty($sessionId)) {
3249
        $sessionId = api_get_session_id();
3250
    } else {
3251
        $sessionId = intval($sessionId);
3252
    }
3253
3254
    $userId = intval($userId);
3255
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3256
    if (empty($parentInfo)) {
3257
        return false;
3258
    }
3259
    $parentId = $parentInfo['id'];
3260
3261
    $sessionCondition = api_get_session_condition($sessionId);
3262
3263
    $sql = "SELECT *
3264
            FROM $work
3265
            WHERE
3266
                user_id = $userId
3267
                $sessionCondition AND
3268
                parent_id = $parentId AND
3269
                c_id = ".$courseInfo['real_id']."
3270
            ORDER BY sent_date DESC
3271
            LIMIT 1
3272
            ";
3273
    $result = Database::query($sql);
3274 View Code Duplication
    if (Database::num_rows($result)) {
3275
        $work = Database::fetch_array($result, 'ASSOC');
3276
        $work['qualification_rounded'] = formatWorkScore($work['qualification'], $parentInfo['qualification']);
3277
3278
        return $work;
3279
    }
3280
3281
    return array();
3282
}
3283
3284
/**
3285
 * @param float $score
3286
 * @param int $weight
3287
 *
3288
 * @return string
3289
 */
3290
function formatWorkScore($score, $weight)
3291
{
3292
    $label = 'info';
3293
    $weight = (int) $weight;
3294
    $relativeScore = 0;
3295
    if (!empty($weight)) {
3296
        $relativeScore = $score / $weight;
3297
    }
3298
    if ($relativeScore < 0.5) {
3299
        $label = 'important';
3300
    } elseif ($relativeScore < 0.75) {
3301
        $label = 'warning';
3302
    }
3303
3304
    return Display::label(
3305
    api_number_format($score, 1).' / '.$weight,
3306
        $label
3307
    );
3308
}
3309
3310
/**
3311
 * @param int $id comment id
3312
 * @param array $courseInfo
3313
 * @return string
3314
 */
3315
function getWorkComment($id, $courseInfo = array())
3316
{
3317
    if (empty($courseInfo)) {
3318
        $courseInfo = api_get_course_info();
3319
    }
3320
3321
    if (empty($courseInfo['real_id'])) {
3322
        return array();
3323
    }
3324
3325
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3326
    $id = intval($id);
3327
3328
    $sql = "SELECT * FROM $commentTable
3329
            WHERE id = $id AND c_id = ".$courseInfo['real_id'];
3330
    $result = Database::query($sql);
3331
    $comment = array();
3332
    if (Database::num_rows($result)) {
3333
        $comment = Database::fetch_array($result, 'ASSOC');
3334
        $filePath = null;
3335
        $fileUrl = null;
3336
        $deleteUrl = null;
3337
        $fileName = null;
3338
        if (!empty($comment['file'])) {
3339
            $work = get_work_data_by_id($comment['work_id']);
3340
            $workParent = get_work_data_by_id($work['parent_id']);
3341
            $filePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/'.$workParent['url'].'/'.$comment['file'];
3342
            $fileUrl = api_get_path(WEB_CODE_PATH).'work/download_comment_file.php?comment_id='.$id.'&'.api_get_cidreq();
3343
            $deleteUrl = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$comment['work_id'].'&action=delete_attachment&comment_id='.$id;
3344
            $fileParts = explode('_', $comment['file']);
3345
            $fileName = str_replace($fileParts[0].'_'.$fileParts[1].'_', '', $comment['file']);
3346
        }
3347
        $comment['delete_file_url'] = $deleteUrl;
3348
        $comment['file_path'] = $filePath;
3349
        $comment['file_url'] = $fileUrl;
3350
        $comment['file_name_to_show'] = $fileName;
3351
        $comment['sent_at_with_label'] = Display::dateToStringAgoAndLongDate($comment['sent_at']);
3352
    }
3353
3354
    return $comment;
3355
}
3356
3357
/**
3358
 * @param int $id
3359
 * @param array $courseInfo
3360
 */
3361
function deleteCommentFile($id, $courseInfo = array())
3362
{
3363
    $workComment = getWorkComment($id, $courseInfo);
3364
    if (isset($workComment['file']) && !empty($workComment['file'])) {
3365
        if (file_exists($workComment['file_path'])) {
3366
            $result = my_delete($workComment['file_path']);
3367
            if ($result) {
3368
                $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3369
                $params = array('file' => '');
3370
                Database::update(
3371
                    $commentTable,
3372
                    $params,
3373
                    array('id = ? AND c_id = ? ' => array($workComment['id'], $workComment['c_id']))
3374
                );
3375
            }
3376
        }
3377
    }
3378
}
3379
3380
/**
3381
 * Adds a comments to the work document
3382
 * @param array $courseInfo
3383
 * @param int $userId
3384
 * @param array $parentWork
3385
 * @param array $work
3386
 * @param array $data
3387
 * @return int
3388
 */
3389
function addWorkComment($courseInfo, $userId, $parentWork, $work, $data)
3390
{
3391
    $fileData = isset($data['attachment']) ? $data['attachment'] : null;
3392
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3393
3394
    // If no attachment and no comment then don't save comment
3395
    if (empty($fileData['name']) && empty($data['comment'])) {
3396
        return false;
3397
    }
3398
3399
    $params = array(
3400
        'work_id' => $work['id'],
3401
        'c_id' => $work['c_id'],
3402
        'user_id' => $userId,
3403
        'comment' => $data['comment'],
3404
        'sent_at' => api_get_utc_datetime()
3405
    );
3406
3407
    $commentId = Database::insert($commentTable, $params);
3408
3409
    if ($commentId) {
3410
        Display::addFlash(
3411
            Display::return_message(get_lang('CommentAdded'))
3412
        );
3413
        $sql = "UPDATE $commentTable SET id = iid WHERE iid = $commentId";
3414
        Database::query($sql);
3415
    }
3416
3417
    $userIdListToSend = array();
3418
    if (api_is_allowed_to_edit()) {
3419
        if (isset($data['send_email']) && $data['send_email']) {
3420
            // Teacher sends a feedback
3421
            $userIdListToSend = array($work['user_id']);
3422
        }
3423
    } else {
3424
        $sessionId = api_get_session_id();
3425
        if (empty($sessionId)) {
3426
            $teachers = CourseManager::get_teacher_list_from_course_code(
3427
                $courseInfo['code']
3428
            );
3429
            if (!empty($teachers)) {
3430
                $userIdListToSend = array_keys($teachers);
3431
            }
3432
        } else {
3433
            $teachers = SessionManager::getCoachesByCourseSession(
3434
                $sessionId,
3435
                $courseInfo['code']
3436
            );
3437
3438
            if (!empty($teachers)) {
3439
                $userIdListToSend = array_values($teachers);
3440
            }
3441
        }
3442
    }
3443
3444
    $url = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$work['id'];
3445
    $subject = sprintf(get_lang('ThereIsANewWorkFeedback'), $parentWork['title']);
3446
    $content = sprintf(get_lang('ThereIsANewWorkFeedbackInWorkXHere'), $work['title'], $url);
3447
3448
    if (!empty($userIdListToSend)) {
3449
        foreach ($userIdListToSend as $userIdToSend) {
3450
            MessageManager::send_message_simple(
3451
                $userIdToSend,
3452
                $subject,
3453
                $content
3454
            );
3455
        }
3456
    }
3457
3458
    $fileData = isset($data['file']) ? $data['file'] : null;
3459
    if (!empty($commentId) && !empty($fileData)) {
3460
        $workParent = get_work_data_by_id($work['parent_id']);
3461
        if (!empty($workParent)) {
3462
            $uploadDir = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work'.$workParent['url'];
3463
            $newFileName = 'comment_'.$commentId.'_'.php2phps(api_replace_dangerous_char($fileData['name']));
3464
            $newFilePath = $uploadDir.'/'.$newFileName;
3465
            $result = move_uploaded_file($fileData['tmp_name'], $newFilePath);
3466
            if ($result) {
3467
                $params = array('file' => $newFileName);
3468
                Database::update(
3469
                    $commentTable,
3470
                    $params,
3471
                    array('id = ? AND c_id = ? ' => array($commentId, $work['c_id']))
3472
                );
3473
            }
3474
        }
3475
    }
3476
}
3477
3478
/**
3479
 * @param array $work
3480
 *
3481
 * @return string
3482
 */
3483
function getWorkCommentForm($work, $workParent)
3484
{
3485
    $url = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$work['id'].'&action=send_comment&'.api_get_cidreq();
3486
    $form = new FormValidator(
3487
        'work_comment',
3488
        'post',
3489
        $url,
3490
        '',
3491
        array('enctype' => "multipart/form-data")
3492
    );
3493
3494
    $qualification = $workParent['qualification'];
3495
3496
    if (api_is_allowed_to_edit()) {
3497
        if (!empty($qualification) && intval($qualification) > 0) {
3498
            $form->addFloat(
3499
                'qualification',
3500
                array(get_lang('Qualification'), " / ".$qualification),
3501
                false,
3502
                [],
3503
                false,
3504
                0,
3505
                $qualification
3506
            );
3507
3508
            $form->addFile('file', get_lang('Correction'));
3509
            $form->setDefaults(['qualification' => $work['qualification']]);
3510
        }
3511
    }
3512
3513
    $form->addHtmlEditor('comment', get_lang('Comment'), false);
3514
    $form->addFile('attachment', get_lang('Attachment'));
3515
    $form->addElement('hidden', 'id', $work['id']);
3516
3517
    if (api_is_allowed_to_edit()) {
3518
        $form->addCheckBox(
3519
            'send_email',
3520
            null,
3521
            get_lang('SendMailToStudent')
3522
        );
3523
    }
3524
3525
    $form->addButtonSend(get_lang('Send'), 'button');
3526
3527
    return $form->returnForm();
3528
}
3529
3530
/**
3531
 * @param array $homework result of get_work_assignment_by_id()
3532
 * @return string
3533
 */
3534
function getWorkDateValidationStatus($homework)
3535
{
3536
    $message = null;
3537
    $has_expired = false;
3538
    $has_ended = false;
3539
3540
    if (!empty($homework)) {
3541 View Code Duplication
        if (!empty($homework['expires_on']) || !empty($homework['ends_on'])) {
3542
            $time_now = time();
3543
3544
            if (!empty($homework['expires_on'])) {
3545
                $time_expires = api_strtotime($homework['expires_on'], 'UTC');
3546
                $difference = $time_expires - $time_now;
3547
                if ($difference < 0) {
3548
                    $has_expired = true;
3549
                }
3550
            }
3551
3552
            if (empty($homework['expires_on'])) {
3553
                $has_expired = false;
3554
            }
3555
3556
            if (!empty($homework['ends_on'])) {
3557
                $time_ends = api_strtotime($homework['ends_on'], 'UTC');
3558
                $difference2 = $time_ends - $time_now;
3559
                if ($difference2 < 0) {
3560
                    $has_ended = true;
3561
                }
3562
            }
3563
3564
            $ends_on = api_convert_and_format_date($homework['ends_on']);
3565
            $expires_on = api_convert_and_format_date($homework['expires_on']);
3566
        }
3567
3568
        if ($has_ended) {
3569
            $message = Display::return_message(get_lang('EndDateAlreadyPassed').' '.$ends_on, 'error');
3570
        } elseif ($has_expired) {
3571
            $message = Display::return_message(get_lang('ExpiryDateAlreadyPassed').' '.$expires_on, 'warning');
3572
        } else {
3573
            if ($has_expired) {
3574
                $message = Display::return_message(get_lang('ExpiryDateToSendWorkIs').' '.$expires_on);
3575
            }
3576
        }
3577
    }
3578
3579
    return array(
3580
        'message' => $message,
3581
        'has_ended' => $has_ended,
3582
        'has_expired' => $has_expired
3583
    );
3584
}
3585
3586
/**
3587
 * @param FormValidator $form
3588
 * @param int $uploadFormType
3589
 */
3590
function setWorkUploadForm($form, $uploadFormType = 0)
3591
{
3592
    $form->addElement('header', get_lang('UploadADocument'));
3593
    $form->addElement('hidden', 'contains_file', 0, array('id'=>'contains_file_id'));
3594
    $form->addElement('hidden', 'active', 1);
3595
    $form->addElement('hidden', 'accepted', 1);
3596
    $form->addElement('text', 'title', get_lang('Title'), array('id' => 'file_upload'));
3597
    $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
3598
3599
    switch ($uploadFormType) {
3600 View Code Duplication
        case 0:
3601
            // File and text.
3602
            $form->addElement('file', 'file', get_lang('UploadADocument'), 'size="40" onchange="updateDocumentTitle(this.value)"');
3603
            $form->addProgress();
3604
            $form->addHtmlEditor('description', get_lang('Description'), false, false, getWorkDescriptionToolbar());
3605
            break;
3606 View Code Duplication
        case 1:
3607
            // Only text.
3608
            $form->addHtmlEditor('description', get_lang('Description'), false, false, getWorkDescriptionToolbar());
3609
            $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required');
3610
            break;
3611
        case 2:
3612
            // Only file.
3613
            $form->addElement('file', 'file', get_lang('UploadADocument'), 'size="40" onchange="updateDocumentTitle(this.value)"');
3614
            $form->addProgress();
3615
            $form->addRule('file', get_lang('ThisFieldIsRequired'), 'required');
3616
            break;
3617
    }
3618
3619
    $form->addButtonUpload(get_lang('Upload'), 'submitWork');
3620
}
3621
3622
/**
3623
 * @param array $my_folder_data
3624
 * @param array $_course
3625
 * @param bool $isCorrection
3626
 * @param array $workInfo
3627
 * @param array $file
3628
 *
3629
 * @return array
3630
 */
3631
function uploadWork($my_folder_data, $_course, $isCorrection = false, $workInfo = [], $file = [])
3632
{
3633
    if (isset($_FILES['file']) && !empty($_FILES['file'])) {
3634
        $file = $_FILES['file'];
3635
    }
3636
3637
    if (empty($file['size'])) {
3638
        return array(
3639
            'error' => Display:: return_message(
3640
                get_lang('UplUploadFailedSizeIsZero'),
3641
                'error'
3642
            )
3643
        );
3644
    }
3645
    $updir = api_get_path(SYS_COURSE_PATH).$_course['path'].'/work/'; //directory path to upload
3646
3647
    // Try to add an extension to the file if it has'nt one
3648
    $filename = add_ext_on_mime(stripslashes($file['name']), $file['type']);
3649
3650
    // Replace dangerous characters
3651
    $filename = api_replace_dangerous_char($filename);
3652
3653
    // Transform any .php file in .phps fo security
3654
    $filename = php2phps($filename);
3655
    $filesize = filesize($file['tmp_name']);
3656
3657
    if (empty($filesize)) {
3658
        return array(
3659
            'error' => Display:: return_message(
3660
                get_lang('UplUploadFailedSizeIsZero'),
3661
                'error'
3662
            )
3663
        );
3664
    } elseif (!filter_extension($new_file_name)) {
3665
        return array(
3666
            'error' => Display:: return_message(
3667
                get_lang('UplUnableToSaveFileFilteredExtension'),
3668
                'error'
3669
            )
3670
        );
3671
    }
3672
3673
    $totalSpace = DocumentManager::documents_total_space($_course['real_id']);
3674
    $course_max_space = DocumentManager::get_course_quota($_course['code']);
3675
    $total_size = $filesize + $totalSpace;
3676
3677
    if ($total_size > $course_max_space) {
3678
        return array(
3679
            'error' => Display :: return_message(get_lang('NoSpace'), 'error')
3680
        );
3681
    }
3682
3683
    // Compose a unique file name to avoid any conflict
3684
    $new_file_name = api_get_unique_id();
3685
3686
    if ($isCorrection) {
3687
        if (!empty($workInfo['url'])) {
3688
            $new_file_name = basename($workInfo['url']).'_correction';
3689
        } else {
3690
            $new_file_name = $new_file_name.'_correction';
3691
        }
3692
    }
3693
3694
    $curdirpath = basename($my_folder_data['url']);
3695
3696
    // If we come from the group tools the groupid will be saved in $work_table
3697
    if (is_dir($updir.$curdirpath) || empty($curdirpath)) {
3698
        $result = move_uploaded_file(
3699
            $file['tmp_name'],
3700
            $updir.$curdirpath.'/'.$new_file_name
3701
        );
3702
3703
    } else {
3704
        return array(
3705
            'error' => Display :: return_message(
3706
                get_lang('FolderDoesntExistsInFileSystem'),
3707
                'error'
3708
            )
3709
        );
3710
    }
3711
3712
    $url = null;
3713
    if ($result) {
3714
        $url = 'work/'.$curdirpath.'/'.$new_file_name;
3715
    } else {
3716
        return false;
3717
    }
3718
3719
    return array(
3720
        'url' => $url,
3721
        'filename' => $filename,
3722
        'filesize' => $filesize,
3723
        'error' => null
3724
    );
3725
}
3726
3727
/**
3728
 * Send an e-mail to users related to this work (course teachers, usually, but
3729
 * might include other group members)
3730
 * @param int $workId
3731
 * @param array $courseInfo
3732
 * @param int $session_id
3733
 */
3734
function sendAlertToUsers($workId, $courseInfo, $session_id)
3735
{
3736
    $user_list = array();
3737
    //$workData = get_work_assignment_by_id($workId, $courseInfo['real_id']);
3738
    $workData = get_work_data_by_id($workId, $courseInfo['real_id'], $session_id);
3739
    //last value is to check this is not "just" an edit
3740
    //YW Tis part serve to send a e-mail to the tutors when a new file is sent
3741
    $send = api_get_course_setting('email_alert_manager_on_new_doc');
3742
3743
    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_TEACHERS) {
3744
        // Lets predefine some variables. Be sure to change the from address!
3745
        if (empty($session_id)) {
3746
            //Teachers
3747
            $user_list = CourseManager::get_user_list_from_course_code(
3748
                api_get_course_id(),
3749
                null,
3750
                null,
3751
                null,
3752
                COURSEMANAGER
3753
            );
3754
        } else {
3755
            // Coaches
3756
            $user_list = CourseManager::get_user_list_from_course_code(
3757
                api_get_course_id(),
3758
                $session_id,
3759
                null,
3760
                null,
3761
                2
3762
            );
3763
        }
3764
    }
3765
3766
    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_STUDENTS) {
3767
        if (!$session_id) {
3768
            $session_id = null;
3769
        }
3770
        $student = CourseManager::get_user_list_from_course_code(
3771
            api_get_course_id(),
3772
            $session_id,
3773
            null,
3774
            null,
3775
            STUDENT,
3776
            null,
3777
            null,
3778
            null,
3779
            null,
3780
            null,
3781
            array(api_get_user_id())
3782
        );
3783
        $user_list = array_merge($user_list, $student);
3784
    }
3785
3786
    if ($send) {
3787
        $senderEmail = api_get_setting('emailAdministrator');
3788
        $senderName = api_get_person_name(
3789
            api_get_setting('administratorName'),
3790
            api_get_setting('administratorSurname'),
3791
            null,
3792
            PERSON_NAME_EMAIL_ADDRESS
3793
        );
3794
        $subject = "[".api_get_setting('siteName')."] ".get_lang('SendMailBody')."\n ".get_lang('CourseName').": ".$courseInfo['name']."  ";
3795
        foreach ($user_list as $user_data) {
0 ignored issues
show
Bug introduced by
The expression $user_list of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3796
            $to_user_id = $user_data['user_id'];
3797
            $user_info = api_get_user_info($to_user_id);
3798
            $message = get_lang('SendMailBody')."\n".get_lang('CourseName')." : ".$courseInfo['name']."\n";
3799
            $message .= get_lang('UserName')." : ".api_get_person_name($user_info['firstname'], $user_info['lastname'])."\n";
3800
            $message .= get_lang('DateSent')." : ".api_format_date(api_get_local_time())."\n";
3801
            $url = api_get_path(WEB_CODE_PATH)."work/work.php?cidReq=".$courseInfo['code']."&id_session=".$session_id."&id=".$workData['id'];
3802
            $message .= get_lang('WorkName')." : ".$workData['title']."\n\n".'<a href="'.$url.'">'.get_lang('DownloadLink')."</a>\n";
3803
            //$message .= $url;
3804
            MessageManager::send_message_simple($to_user_id, $subject, $message);
3805
            api_mail_html(
3806
                api_get_person_name(
3807
                    $user_info['firstname'].' '.$user_info['lastname'],
3808
                    null,
3809
                    PERSON_NAME_EMAIL_ADDRESS
3810
                ),
3811
                $user_info['email'],
3812
                $subject,
3813
                $message,
3814
                $senderName,
3815
                $senderEmail
3816
            );
3817
        }
3818
    }
3819
}
3820
3821
/**
3822
 * Check if the current uploaded work filename already exists in the current assement
3823
 *
3824
 * @param $filename
3825
 * @param $workId
3826
 * @return mixed
3827
 */
3828 View Code Duplication
function checkExistingWorkFileName($filename, $workId)
3829
{
3830
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3831
    $filename = Database::escape_string($filename);
3832
    $sql = "SELECT title FROM $work_table
3833
            WHERE parent_id = $workId AND title = '$filename' AND active = 1";
3834
    $result = Database::query($sql);
3835
    return Database::fetch_assoc($result);
3836
}
3837
3838
/**
3839
 * @param array $workInfo
3840
 * @param array $values
3841
 * @param array $courseInfo
3842
 * @param int $sessionId
3843
 * @param int $groupId
3844
 * @param int $userId
3845
 * @param array $file
3846
 * @param bool  $checkDuplicated
3847
 * @param bool  $showFlashMessage
3848
 *
3849
 * @return null|string
3850
 */
3851
function processWorkForm(
3852
    $workInfo,
3853
    $values,
3854
    $courseInfo,
3855
    $sessionId,
3856
    $groupId,
3857
    $userId,
3858
    $file = [],
3859
    $checkDuplicated = false,
3860
    $showFlashMessage = true
3861
) {
3862
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3863
3864
    $courseId = $courseInfo['real_id'];
3865
    $groupId = intval($groupId);
3866
    $sessionId = intval($sessionId);
3867
    $userId = intval($userId);
3868
3869
    $title = $values['title'];
3870
    $description = $values['description'];
3871
    $contains_file = isset($values['contains_file']) && !empty($values['contains_file']) ? intval($values['contains_file']) : 0;
3872
3873
    $saveWork = true;
3874
    $filename = null;
3875
    $url = null;
3876
    $filesize = null;
3877
    $workData = [];
3878
    $message = null;
3879
3880
    if ($values['contains_file']) {
3881
        if ($checkDuplicated) {
3882
            if (checkExistingWorkFileName($file['name'], $workInfo['id'])) {
3883
                $saveWork = false;
3884
                $result['error'] = get_lang('YouAlreadySentThisFile');
3885
                $workData['error'] = get_lang('UplAlreadyExists');
3886
            } else {
3887
                $result = uploadWork($workInfo, $courseInfo, false, [], $file);
3888
            }
3889
        } else {
3890
            $result = uploadWork($workInfo, $courseInfo, false, [], $file);
3891
        }
3892
3893
        if (isset($result['error'])) {
3894
            if ($showFlashMessage) {
3895
                $message = $result['error'];
3896
            }
3897
3898
            $saveWork = false;
3899
        }
3900
    }
3901
3902
    if ($saveWork) {
3903
        $filename = isset($result['filename']) ? $result['filename'] : null;
3904
        if (empty($title)) {
3905
            $title = isset($result['title']) && !empty($result['title']) ? $result['title'] : get_lang('Untitled');
3906
        }
3907
        $filesize = isset($result['filesize']) ? $result['filesize'] : null;
3908
        $url = isset($result['url']) ? $result['url'] : null;
3909
    }
3910
3911
    if (empty($title)) {
3912
        $title = get_lang('Untitled');
3913
    }
3914
3915
    $groupIid = 0;
3916
    $groupInfo = [];
3917
    if ($groupId) {
3918
        $groupInfo = GroupManager::get_group_properties($groupId);
3919
        $groupIid = $groupInfo['iid'];
3920
    }
3921
3922
    if ($saveWork) {
3923
        $active = '1';
3924
        $params = [
3925
            'c_id' => $courseId,
3926
            'url' => $url,
3927
            'filetype' => 'file',
3928
            'title' => $title,
3929
            'description' => $description,
3930
            'contains_file' => $contains_file,
3931
            'active' => $active,
3932
            'accepted' => '1',
3933
            'qualificator_id' => 0,
3934
            'document_id' => 0,
3935
            'weight' => 0,
3936
            'allow_text_assignment' => 0,
3937
            'post_group_id' => $groupIid,
3938
            'sent_date' => api_get_utc_datetime(),
3939
            'parent_id' => $workInfo['id'],
3940
            'session_id' => $sessionId ? $sessionId : null,
3941
            'user_id' => $userId,
3942
            'has_properties' => 0,
3943
            'qualification' => 0
3944
            //'filesize' => $filesize
3945
        ];
3946
        $workId = Database::insert($work_table, $params);
3947
3948
        if ($workId) {
3949
            $sql = "UPDATE $work_table SET id = iid WHERE iid = $workId ";
3950
            Database::query($sql);
3951
3952
            if (array_key_exists('filename', $workInfo) && !empty($filename)) {
3953
                $filename = Database::escape_string($filename);
3954
                $sql = "UPDATE $work_table SET
3955
                            filename = '$filename'
3956
                        WHERE iid = $workId";
3957
                Database::query($sql);
3958
            }
3959
3960
            if (array_key_exists('document_id', $workInfo)) {
3961
                $documentId = isset($values['document_id']) ? intval($values['document_id']) : 0;
3962
                $sql = "UPDATE $work_table SET
3963
                            document_id = '$documentId'
3964
                        WHERE iid = $workId";
3965
                Database::query($sql);
3966
            }
3967
            api_item_property_update(
3968
                $courseInfo,
3969
                'work',
3970
                $workId,
3971
                'DocumentAdded',
3972
                $userId,
3973
                $groupInfo
3974
            );
3975
            sendAlertToUsers($workId, $courseInfo, $sessionId);
3976
            Event::event_upload($workId);
3977
3978
            // The following feature requires the creation of a work-type
3979
            // extra_field and the following setting in the configuration file
3980
            // (until moved to the database). It allows te teacher to set a
3981
            // "considered work time", meaning the time we assume a student
3982
            // would have spent, approximately, to prepare the task before
3983
            // handing it in Chamilo, adding this time to the student total
3984
            // course use time, as a register of time spent *before* his
3985
            // connection to the platform to hand the work in.
3986
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
3987
3988
            if (!empty($consideredWorkingTime)) {
3989
                // Get the "considered work time" defined for this work
3990
                $fieldValue = new ExtraFieldValue('work');
3991
                $resultExtra = $fieldValue->getAllValuesForAnItem(
3992
                    $workInfo['iid'], //the ID of the work *folder*, not the document uploaded by the student
3993
                    true
3994
                );
3995
3996
                $workingTime = null;
3997 View Code Duplication
                foreach ($resultExtra as $field) {
3998
                    $field = $field['value'];
3999
                    if ($consideredWorkingTime == $field->getField()->getVariable()) {
4000
                        $workingTime = $field->getValue();
4001
                    }
4002
                }
4003
4004
                // If no time was defined, or a time of "0" was set, do nothing
4005
                if (!empty($workingTime)) {
4006
                    // If some time is set, get the list of docs handed in by
4007
                    // this student (to make sure we count the time only once)
4008
                    $userWorks = get_work_user_list(
4009
                        0,
4010
                        100,
4011
                        null,
4012
                        null,
4013
                        $workInfo['id'],
4014
                        null,
4015
                        $userId,
4016
                        false,
4017
                        $courseId,
4018
                        $sessionId
4019
                    );
4020
4021
                    if (count($userWorks) == 1) {
4022
                        // The student only uploaded one doc so far, so add the
4023
                        // considered work time to his course connection time
4024
                        $ip = api_get_real_ip();
4025
                        Event::eventAddVirtualCourseTime($courseId, $userId, $sessionId, $workingTime, $ip);
4026
                    }
4027
                }
4028
            }
4029
            $workData = get_work_data_by_id($workId);
4030
            if ($showFlashMessage) {
4031
                Display::addFlash(Display::return_message(get_lang('DocAdd')));
4032
            }
4033
        }
4034
    } else {
4035
        if ($showFlashMessage) {
4036
            Display::addFlash(
4037
                Display::return_message(
4038
                    $message ? $message : get_lang('IsNotPosibleSaveTheDocument'),
4039
                    'error'
4040
                )
4041
            );
4042
        }
4043
    }
4044
4045
    return $workData;
4046
}
4047
4048
/**
4049
 * Creates a new task (directory) in the assignment tool
4050
 * @param array $formValues
4051
 * @param int $user_id
4052
 * @param array $courseInfo
4053
 * @param int $groupId
4054
 * @param int $session_id
4055
 * @return bool|int
4056
 * @note $params can have the following elements, but should at least have the 2 first ones: (
4057
 *       'new_dir' => 'some-name',
4058
 *       'description' => 'some-desc',
4059
 *       'qualification' => 20 (e.g. 20),
4060
 *       'weight' => 50 (percentage) to add to gradebook (e.g. 50),
4061
 *       'allow_text_assignment' => 0/1/2,
4062
 * @todo Rename createAssignment or createWork, or something like that
4063
 */
4064
function addDir($formValues, $user_id, $courseInfo, $groupId, $session_id)
4065
{
4066
    $em = Database::getManager();
4067
4068
    $user_id = intval($user_id);
4069
    $groupId = intval($groupId);
4070
4071
    $groupIid = 0;
4072
    $groupInfo = [];
4073
    if (!empty($groupId)) {
4074
        $groupInfo = GroupManager::get_group_properties($groupId);
4075
        $groupIid = $groupInfo['iid'];
4076
    }
4077
    $session = $em->find('ChamiloCoreBundle:Session', $session_id);
4078
4079
    $base_work_dir = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work';
4080
    $course_id = $courseInfo['real_id'];
4081
4082
    $directory = api_replace_dangerous_char($formValues['new_dir']);
4083
    $directory = disable_dangerous_file($directory);
4084
    $created_dir = create_unexisting_work_directory($base_work_dir, $directory);
4085
4086
    if (empty($created_dir)) {
4087
        return false;
4088
    }
4089
4090
    $enableEndDate = isset($formValues['enableEndDate']) ? true : false;
4091
    $enableExpiryDate = isset($formValues['enableExpiryDate']) ? true : false;
4092
4093
    if ($enableEndDate && $enableExpiryDate) {
4094
        if ($formValues['expires_on'] > $formValues['ends_on']) {
4095
            Display::addFlash(
4096
                Display::return_message(
4097
                    get_lang('DateExpiredNotBeLessDeadLine'),
4098
                    'warning'
4099
                )
4100
            );
4101
            return false;
4102
        }
4103
    }
4104
4105
    $dirName = '/'.$created_dir;
4106
    $today = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
4107
4108
    $workTable = new CStudentPublication();
4109
    $workTable
4110
        ->setCId($course_id)
4111
        ->setUrl($dirName)
4112
        ->setTitle($formValues['new_dir'])
4113
        ->setDescription($formValues['description'])
4114
        ->setActive(true)
4115
        ->setAccepted(true)
4116
        ->setFiletype('folder')
4117
        ->setPostGroupId($groupIid)
4118
        ->setSentDate($today)
4119
        ->setQualification($formValues['qualification'] != '' ? $formValues['qualification'] : 0)
4120
        ->setParentId(0)
4121
        ->setQualificatorId(0)
4122
        ->setWeight(!empty($formValues['weight']) ? $formValues['weight'] : 0)
4123
        ->setSession($session)
0 ignored issues
show
Bug introduced by
It seems like $session defined by $em->find('ChamiloCoreBu...:Session', $session_id) on line 4077 can also be of type object; however, Chamilo\CourseBundle\Ent...blication::setSession() does only seem to accept null|object<Chamilo\CoreBundle\Entity\Session>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4124
        ->setAllowTextAssignment($formValues['allow_text_assignment'])
4125
        ->setContainsFile(0)
4126
        ->setUserId($user_id)
4127
        ->setHasProperties(0)
4128
        ->setDocumentId(0);
4129
4130
    $em->persist($workTable);
4131
    $em->flush();
4132
4133
    $workTable->setId($workTable->getIid());
4134
    $em->merge($workTable);
4135
    $em->flush();
4136
4137
    // Folder created
4138
    api_item_property_update(
4139
        $courseInfo,
4140
        'work',
4141
        $workTable->getIid(),
4142
        'DirectoryCreated',
4143
        $user_id,
4144
        $groupInfo
4145
    );
4146
4147
    updatePublicationAssignment(
4148
        $workTable->getIid(),
4149
        $formValues,
4150
        $courseInfo,
4151
        $groupIid
4152
    );
4153
4154
    // Added the new Work ID to the extra field values
4155
    $formValues['item_id'] = $workTable->getIid();
4156
4157
    $workFieldValue = new ExtraFieldValue('work');
4158
    $workFieldValue->saveFieldValues($formValues);
4159
4160
    $sendEmailAlert = api_get_course_setting('email_alert_students_on_new_homework');
4161
4162
    switch ($sendEmailAlert) {
4163
        case 1:
4164
            sendEmailToStudentsOnHomeworkCreation(
4165
                $course_id,
4166
                $session ? $session->getId() : 0,
4167
                $workTable->getIid()
4168
            );
4169
            break;
4170
        case 2:
4171
            sendEmailToDrhOnHomeworkCreation(
4172
                $course_id,
4173
                $workTable->getIid(),
4174
                $session ? $session->getId() : 0
4175
            );
4176
            break;
4177
    }
4178
4179
    return $workTable->getIid();
4180
}
4181
4182
/**
4183
 * @param int $workId
4184
 * @param array $courseInfo
4185
 * @return int
4186
 */
4187 View Code Duplication
function agendaExistsForWork($workId, $courseInfo)
4188
{
4189
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
4190
    $courseId = $courseInfo['real_id'];
4191
    $workId = intval($workId);
4192
4193
    $sql = "SELECT add_to_calendar FROM $workTable
4194
            WHERE c_id = $courseId AND publication_id = ".$workId;
4195
    $res = Database::query($sql);
4196
    if (Database::num_rows($res)) {
4197
        $row = Database::fetch_array($res, 'ASSOC');
4198
        if (!empty($row['add_to_calendar'])) {
4199
            return $row['add_to_calendar'];
4200
        }
4201
    }
4202
    return 0;
4203
}
4204
4205
/**
4206
 * Update work description, qualification, weight, allow_text_assignment
4207
 * @param int $workId (iid)
4208
 * @param array $params
4209
 * @param array $courseInfo
4210
 * @param int $sessionId
4211
 */
4212
function updateWork($workId, $params, $courseInfo, $sessionId = 0)
4213
{
4214
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4215
    $filteredParams = array(
4216
        'description' => $params['description'],
4217
        'qualification' => $params['qualification'],
4218
        'weight' => $params['weight'],
4219
        'allow_text_assignment' => $params['allow_text_assignment']
4220
    );
4221
4222
    Database::update(
4223
        $workTable,
4224
        $filteredParams,
4225
        array(
4226
            'iid = ? AND c_id = ?' => array(
4227
                $workId,
4228
                $courseInfo['real_id']
4229
            )
4230
        )
4231
    );
4232
4233
    $workFieldValue = new ExtraFieldValue('work');
4234
    $workFieldValue->saveFieldValues($params);
4235
}
4236
4237
/**
4238
 * @param int $workId
4239
 * @param array $params
4240
 * @param array $courseInfo
4241
 * @param int $groupId
4242
 */
4243
function updatePublicationAssignment($workId, $params, $courseInfo, $groupId)
4244
{
4245
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
4246
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4247
    $workId = intval($workId);
4248
    $now = api_get_utc_datetime();
4249
    $course_id = $courseInfo['real_id'];
4250
4251
    // Insert into agenda
4252
    $agendaId = 0;
4253
    if (isset($params['add_to_calendar']) && $params['add_to_calendar'] == 1) {
4254
        // Setting today date
4255
        $date = $end_date = $now;
4256
4257
        if (isset($params['enableExpiryDate'])) {
4258
            $end_date = $params['expires_on'];
4259
            $date = $end_date;
4260
        }
4261
4262
        $title = sprintf(get_lang('HandingOverOfTaskX'), $params['new_dir']);
4263
        $description = isset($params['description']) ? $params['description'] : '';
4264
        $content = '<a href="'.api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq().'&id='.$workId.'">'
4265
            .$params['new_dir'].'</a>'.$description;
4266
4267
        $agendaId = agendaExistsForWork($workId, $courseInfo);
4268
4269
        // Add/edit agenda
4270
        $agenda = new Agenda('course');
4271
        $agenda->set_course($courseInfo);
4272
4273
        if (!empty($agendaId)) {
4274
            // add_to_calendar is set but it doesnt exists then invalidate
4275
            $eventInfo = $agenda->get_event($agendaId);
4276
            if (empty($eventInfo)) {
4277
                $agendaId = 0;
4278
            }
4279
        }
4280
4281
        $eventColor = $agenda->eventStudentPublicationColor;
4282
4283
        if (empty($agendaId)) {
4284
            $agendaId = $agenda->addEvent(
4285
                $date,
4286
                $end_date,
4287
                'false',
4288
                $title,
4289
                $content,
4290
                array('GROUP:'.$groupId),
4291
                false,
4292
                null,
4293
                [],
4294
                [],
4295
                null,
4296
                $eventColor
4297
            );
4298
        } else {
4299
            $agenda->editEvent(
4300
                $agendaId,
4301
                $end_date,
4302
                $end_date,
4303
                'false',
4304
                $title,
4305
                $content,
4306
                [],
4307
                [],
4308
                [],
4309
                null,
4310
                $eventColor
4311
            );
4312
        }
4313
    }
4314
4315
    $qualification = isset($params['qualification']) && !empty($params['qualification']) ? 1 : 0;
4316
    $expiryDate = isset($params['enableExpiryDate']) && (int) $params['enableExpiryDate'] == 1 ? api_get_utc_datetime($params['expires_on']) : '';
4317
    $endDate = isset($params['enableEndDate']) && (int) $params['enableEndDate'] == 1 ? api_get_utc_datetime($params['ends_on']) : '';
4318
4319
    $data = get_work_assignment_by_id($workId, $course_id);
4320
4321
    if (!empty($expiryDate)) {
4322
        $expiryDateCondition = "expires_on = '".Database::escape_string($expiryDate)."', ";
0 ignored issues
show
Bug introduced by
It seems like $expiryDate defined by isset($params['enableExp...ams['expires_on']) : '' on line 4316 can also be of type object<DateTime>; however, Database::escape_string() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4323
    } else {
4324
        $expiryDateCondition = "expires_on = null, ";
4325
    }
4326
4327
    if (!empty($endDate)) {
4328
        $endOnCondition = "ends_on = '".Database::escape_string($endDate)."', ";
0 ignored issues
show
Bug introduced by
It seems like $endDate defined by isset($params['enableEnd...params['ends_on']) : '' on line 4317 can also be of type object<DateTime>; however, Database::escape_string() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
4329
    } else {
4330
        $endOnCondition = "ends_on = null, ";
4331
    }
4332
4333
    if (empty($data)) {
4334
        $sql = "INSERT INTO $table SET
4335
                c_id = $course_id ,
4336
                $expiryDateCondition
4337
                $endOnCondition
4338
                add_to_calendar = $agendaId,
4339
                enable_qualification = '$qualification',
4340
                publication_id = '$workId'";
4341
        Database::query($sql);
4342
        $my_last_id = Database::insert_id();
4343
4344
        if ($my_last_id) {
4345
            $sql = "UPDATE $table SET
4346
                        id = iid
4347
                    WHERE iid = $my_last_id";
4348
            Database::query($sql);
4349
4350
            $sql = "UPDATE $workTable SET
4351
                        has_properties  = $my_last_id,
4352
                        view_properties = 1
4353
                    WHERE c_id = $course_id AND id = $workId";
4354
            Database::query($sql);
4355
        }
4356
    } else {
4357
        $sql = "UPDATE $table SET
4358
                    $expiryDateCondition
4359
                    $endOnCondition
4360
                    add_to_calendar  = $agendaId,
4361
                    enable_qualification = '".$qualification."'
4362
                WHERE
4363
                    publication_id = $workId AND
4364
                    c_id = $course_id AND
4365
                    iid = ".$data['iid'];
4366
        Database::query($sql);
4367
    }
4368
4369
    if (!empty($params['category_id'])) {
4370
        $link_info = GradebookUtils::isResourceInCourseGradebook(
4371
            $courseInfo['real_id'],
4372
            LINK_STUDENTPUBLICATION,
4373
            $workId,
4374
            api_get_session_id()
4375
        );
4376
4377
        $linkId = null;
4378
        if (!empty($link_info)) {
4379
            $linkId = $link_info['id'];
4380
        }
4381
4382
        if (isset($params['make_calification']) &&
4383
            $params['make_calification'] == 1
4384
        ) {
4385
            if (empty($linkId)) {
4386
                GradebookUtils::add_resource_to_course_gradebook(
4387
                    $params['category_id'],
4388
                    $courseInfo['code'],
4389
                    LINK_STUDENTPUBLICATION,
4390
                    $workId,
4391
                    $params['new_dir'],
4392
                    api_float_val($params['weight']),
4393
                    api_float_val($params['qualification']),
4394
                    $params['description'],
4395
                    1,
4396
                    api_get_session_id()
4397
                );
4398
            } else {
4399
                GradebookUtils::updateResourceFromCourseGradebook(
4400
                    $linkId,
4401
                    $courseInfo['real_id'],
4402
                    $params['weight']
4403
                );
4404
            }
4405
        } else {
4406
            // Delete everything of the gradebook for this $linkId
4407
            GradebookUtils::remove_resource_from_course_gradebook($linkId);
4408
        }
4409
    }
4410
}
4411
4412
/**
4413
 * Delete all work by student
4414
 * @param int $userId
4415
 * @param array $courseInfo
4416
 * @return array return deleted items
4417
 */
4418
function deleteAllWorkPerUser($userId, $courseInfo)
4419
{
4420
    $deletedItems = array();
4421
    $workPerUser = getWorkPerUser($userId);
4422
    if (!empty($workPerUser)) {
4423
        foreach ($workPerUser as $work) {
4424
            $work = $work['work'];
4425
            foreach ($work->user_results as $userResult) {
4426
                $result = deleteWorkItem($userResult['id'], $courseInfo);
4427
                if ($result) {
4428
                    $deletedItems[] = $userResult;
4429
                }
4430
            }
4431
        }
4432
    }
4433
    return $deletedItems;
4434
}
4435
4436
/**
4437
 * @param int $item_id
4438
 * @param array course info
4439
 * @return bool
4440
 */
4441
function deleteWorkItem($item_id, $courseInfo)
4442
{
4443
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4444
    $TSTDPUBASG = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
4445
    $currentCourseRepositorySys = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
4446
    $is_allowed_to_edit = api_is_allowed_to_edit();
4447
    $file_deleted = false;
4448
    $item_id = intval($item_id);
4449
4450
    $is_author = user_is_author($item_id);
4451
    $work_data = get_work_data_by_id($item_id);
4452
    $locked = api_resource_is_locked_by_gradebook($work_data['parent_id'], LINK_STUDENTPUBLICATION);
4453
    $course_id = $courseInfo['real_id'];
4454
4455
    if (($is_allowed_to_edit && $locked == false) ||
4456
        (
4457
            $locked == false &&
4458
            $is_author &&
4459
            api_get_course_setting('student_delete_own_publication') == 1 &&
4460
            $work_data['qualificator_id'] == 0
4461
        )
4462
    ) {
4463
        // We found the current user is the author
4464
        $sql = "SELECT url, contains_file, user_id, session_id, parent_id FROM $work_table
4465
                WHERE c_id = $course_id AND id = $item_id";
4466
        $result = Database::query($sql);
4467
        $row = Database::fetch_array($result);
4468
        $count = Database::num_rows($result);
4469
4470
        if ($count > 0) {
4471
4472
            // If the "considered_working_time" option is enabled, check
4473
            // whether some time should be removed from track_e_course_access
4474
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
4475
            if ($consideredWorkingTime) {
4476
                $userWorks = get_work_user_list(
4477
                    0,
4478
                    100,
4479
                    null,
4480
                    null,
4481
                    $row['parent_id'],
4482
                    null,
4483
                    $row['user_id'],
4484
                    false,
4485
                    $course_id,
4486
                    $row['session_id']
4487
                );
4488
                // We're only interested in deleting the time if this is the latest work sent
4489
                if (count($userWorks) == 1) {
4490
                    // Get the "considered work time" defined for this work
4491
                    $fieldValue = new ExtraFieldValue('work');
4492
                    $resultExtra = $fieldValue->getAllValuesForAnItem(
4493
                        $row['parent_id'],
4494
                        true
4495
                    );
4496
4497
                    $workingTime = null;
4498 View Code Duplication
                    foreach ($resultExtra as $field) {
4499
                        $field = $field['value'];
4500
4501
                        if ($consideredWorkingTime == $field->getField()->getVariable()) {
4502
                            $workingTime = $field->getValue();
4503
                        }
4504
                    }
4505
                    // If no time was defined, or a time of "0" was set, do nothing
4506
                    if (!empty($workingTime)) {
4507
                        $sessionId = empty($row['session_id']) ? 0 : $row['session_id'];
4508
                        // Getting false from the following call would mean the
4509
                        // time record
4510
                        Event::eventRemoveVirtualCourseTime(
4511
                            $course_id,
4512
                            $row['user_id'],
4513
                            $sessionId,
4514
                            $workingTime
4515
                        );
4516
                    }
4517
                }
4518
            } // end of considered_working_time check section
4519
4520
            $sql = "UPDATE $work_table SET active = 2
4521
                    WHERE c_id = $course_id AND id = $item_id";
4522
            Database::query($sql);
4523
            $sql = "DELETE FROM $TSTDPUBASG
4524
                    WHERE c_id = $course_id AND publication_id = $item_id";
4525
            Database::query($sql);
4526
4527
            api_item_property_update(
4528
                $courseInfo,
4529
                'work',
4530
                $item_id,
4531
                'DocumentDeleted',
4532
                api_get_user_id()
4533
            );
4534
4535
            Event::addEvent(
4536
                LOG_WORK_FILE_DELETE,
4537
                LOG_WORK_DATA,
4538
                [
4539
                    'id' => $work_data['id'],
4540
                    'url' => $work_data['url'],
4541
                    'title' => $work_data['title']
4542
                ],
4543
                null,
4544
                api_get_user_id(),
4545
                api_get_course_int_id(),
4546
                api_get_session_id()
4547
            );
4548
4549
            $work = $row['url'];
4550
4551
            if ($row['contains_file'] == 1) {
4552
                if (!empty($work)) {
4553
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
4554
                        my_delete($currentCourseRepositorySys.'/'.$work);
4555
                        $file_deleted = true;
4556
                    } else {
4557
                        $extension = pathinfo($work, PATHINFO_EXTENSION);
4558
                        $new_dir = $work.'_DELETED_'.$item_id.'.'.$extension;
4559
4560
                        if (file_exists($currentCourseRepositorySys.'/'.$work)) {
4561
                            rename($currentCourseRepositorySys.'/'.$work, $currentCourseRepositorySys.'/'.$new_dir);
4562
                            $file_deleted = true;
4563
                        }
4564
                    }
4565
                }
4566
            } else {
4567
                $file_deleted = true;
4568
            }
4569
        }
4570
    }
4571
4572
    return $file_deleted;
4573
}
4574
4575
/**
4576
 * @param FormValidator $form
4577
 * @param array $defaults
4578
 * @param integer $workId
4579
 * @return FormValidator
4580
 */
4581
function getFormWork($form, $defaults = array(), $workId = 0)
4582
{
4583
    $sessionId = api_get_session_id();
4584
    if (!empty($defaults)) {
4585
        if (isset($defaults['submit'])) {
4586
            unset($defaults['submit']);
4587
        }
4588
    }
4589
4590
    // Create the form that asks for the directory name
4591
    $form->addText('new_dir', get_lang('AssignmentName'));
4592
    $form->addHtmlEditor(
4593
        'description',
4594
        get_lang('Description'),
4595
        false,
4596
        false,
4597
        getWorkDescriptionToolbar()
4598
    );
4599
    $form->addButtonAdvancedSettings('advanced_params', get_lang('AdvancedParameters'));
4600
4601
    if (!empty($defaults) && (isset($defaults['enableEndDate']) || isset($defaults['enableExpiryDate']))) {
4602
        $form->addHtml('<div id="advanced_params_options" style="display:block">');
4603
    } else {
4604
        $form->addHtml('<div id="advanced_params_options" style="display:none">');
4605
    }
4606
4607
    // QualificationOfAssignment
4608
    $form->addElement('text', 'qualification', get_lang('QualificationNumeric'));
4609
4610
    if (($sessionId != 0 && Gradebook::is_active()) || $sessionId == 0) {
4611
        $form->addElement(
4612
            'checkbox',
4613
            'make_calification',
4614
            null,
4615
            get_lang('MakeQualifiable'),
4616
            array(
4617
                'id' =>'make_calification_id',
4618
                'onclick' => "javascript: if(this.checked) { document.getElementById('option1').style.display='block';}else{document.getElementById('option1').style.display='none';}"
4619
            )
4620
        );
4621
    } else {
4622
        // QualificationOfAssignment
4623
        $form->addElement('hidden', 'make_calification', false);
4624
    }
4625
4626
    if (!empty($defaults) && isset($defaults['category_id'])) {
4627
        $form->addHtml('<div id=\'option1\' style="display:block">');
4628
    } else {
4629
        $form->addHtml('<div id=\'option1\' style="display:none">');
4630
    }
4631
4632
    // Loading Gradebook select
4633
    GradebookUtils::load_gradebook_select_in_tool($form);
4634
4635
    $form->addElement('text', 'weight', get_lang('WeightInTheGradebook'));
4636
    $form->addHtml('</div>');
4637
4638
    $form->addElement('checkbox', 'enableExpiryDate', null, get_lang('EnableExpiryDate'), 'id="expiry_date"');
4639
    if (isset($defaults['enableExpiryDate']) && $defaults['enableExpiryDate']) {
4640
        $form->addHtml('<div id="option2" style="display: block;">');
4641
    } else {
4642
        $form->addHtml('<div id="option2" style="display: none;">');
4643
    }
4644
4645
    $timeNextWeek = time()+86400*7;
4646
    $nextWeek = substr(api_get_local_time($timeNextWeek), 0, 10);
4647
    if (!isset($defaults['expires_on'])) {
4648
        $date = substr($nextWeek, 0, 10);
4649
        $defaults['expires_on'] = $date.' 23:59';
4650
    }
4651
4652
    $form->addElement('date_time_picker', 'expires_on', get_lang('ExpiresAt'));
4653
    $form->addHtml('</div>');
4654
    $form->addElement('checkbox', 'enableEndDate', null, get_lang('EnableEndDate'), 'id="end_date"');
4655
4656
    if (!isset($defaults['ends_on'])) {
4657
        $nextDay = substr(api_get_local_time($timeNextWeek+86400), 0, 10);
4658
        $date = substr($nextDay, 0, 10);
4659
        $defaults['ends_on'] = $date.' 23:59';
4660
    }
4661
    if (isset($defaults['enableEndDate']) && $defaults['enableEndDate']) {
4662
        $form->addHtml('<div id="option3" style="display: block;">');
4663
    } else {
4664
        $form->addHtml('<div id="option3" style="display: none;">');
4665
    }
4666
4667
    $form->addElement('date_time_picker', 'ends_on', get_lang('EndsAt'));
4668
    $form->addHtml('</div>');
4669
4670
    $form->addElement('checkbox', 'add_to_calendar', null, get_lang('AddToCalendar'));
4671
    $form->addElement('select', 'allow_text_assignment', get_lang('DocumentType'), getUploadDocumentType());
4672
4673
    // Extra fields
4674
    $extra_field = new ExtraField('work');
4675
    $extra = $extra_field->addElements($form, $workId);
4676
4677
    $htmlHeadXtra[] = '
4678
        <script>
4679
        $(function() {
4680
            ' . $extra['jquery_ready_content'].'
4681
        });
4682
        </script>';
4683
4684
    $form->addHtml('</div>');
4685
    if (!empty($defaults)) {
4686
        $form->setDefaults($defaults);
4687
    }
4688
4689
    return $form;
4690
}
4691
4692
/**
4693
 * @return array
4694
 */
4695
function getUploadDocumentType()
4696
{
4697
    return array(
4698
        0 => get_lang('AllowFileOrText'),
4699
        1 => get_lang('AllowOnlyText'),
4700
        2 => get_lang('AllowOnlyFiles')
4701
    );
4702
}
4703
4704
/**
4705
 * @param array $courseInfo
4706
 * @param bool $showScore
4707
 * @param bool $studentDeleteOwnPublication
4708
 */
4709
function updateSettings($courseInfo, $showScore, $studentDeleteOwnPublication)
4710
{
4711
    $showScore = intval($showScore);
4712
    $courseId = api_get_course_int_id();
4713
    $main_course_table = Database::get_main_table(TABLE_MAIN_COURSE);
4714
    $table_course_setting = Database::get_course_table(TOOL_COURSE_SETTING);
4715
4716
    if (empty($courseId)) {
4717
        return false;
4718
    }
4719
4720
    $query = "UPDATE $main_course_table
4721
              SET show_score = '$showScore'
4722
              WHERE id = $courseId";
4723
    Database::query($query);
4724
4725
    /**
4726
     * Course data are cached in session so we need to update both the database
4727
     * and the session data
4728
     */
4729
    $_course['show_score'] = $showScore;
4730
    Session::write('_course', $courseInfo);
4731
4732
    // changing the tool setting: is a student allowed to delete his/her own document
4733
4734
    // counting the number of occurrences of this setting (if 0 => add, if 1 => update)
4735
    $query = "SELECT * FROM $table_course_setting
4736
              WHERE
4737
                c_id = $courseId AND
4738
                variable = 'student_delete_own_publication'";
4739
4740
    $result = Database::query($query);
4741
    $number_of_setting = Database::num_rows($result);
4742
4743
    if ($number_of_setting == 1) {
4744
        $query = "UPDATE ".$table_course_setting." SET
4745
                  value='" . Database::escape_string($studentDeleteOwnPublication)."'
4746
                  WHERE variable = 'student_delete_own_publication' AND c_id = $courseId";
4747
        Database::query($query);
4748
    } else {
4749
        $params = [
4750
            'c_id' => $courseId,
4751
            'variable' => 'student_delete_own_publication',
4752
            'value' => $studentDeleteOwnPublication,
4753
            'category' => 'work'
4754
        ];
4755
        Database::insert($table_course_setting, $params);
4756
    }
4757
}
4758
4759
/**
4760
 * @param int $item_id
4761
 * @param array $course_info
4762
 */
4763
function makeVisible($item_id, $course_info)
4764
{
4765
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4766
    $course_id = $course_info['real_id'];
4767
    $item_id = intval($item_id);
4768
4769
    $sql = "UPDATE $work_table SET accepted = 1
4770
            WHERE c_id = $course_id AND id = $item_id";
4771
    Database::query($sql);
4772
    api_item_property_update($course_info, 'work', $item_id, 'visible', api_get_user_id());
4773
}
4774
4775
/**
4776
 * @param int $item_id
4777
 * @param array $course_info
4778
 */
4779
function makeInvisible($item_id, $course_info)
4780
{
4781
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4782
    $item_id = intval($item_id);
4783
    $course_id = $course_info['real_id'];
4784
    $sql = "UPDATE  ".$work_table."
4785
            SET accepted = 0
4786
            WHERE c_id = $course_id AND id = '".$item_id."'";
4787
    Database::query($sql);
4788
    api_item_property_update(
4789
        $course_info,
4790
        'work',
4791
        $item_id,
4792
        'invisible',
4793
        api_get_user_id()
4794
    );
4795
}
4796
4797
/**
4798
 * @param int $item_id
4799
 * @param string $path
4800
 * @param array $courseInfo
4801
 * @param int $groupId iid
4802
 * @param int $sessionId
4803
 * @return string
4804
 */
4805
function generateMoveForm($item_id, $path, $courseInfo, $groupId, $sessionId)
4806
{
4807
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4808
    $courseId = $courseInfo['real_id'];
4809
    $folders = array();
4810
    $session_id = intval($sessionId);
4811
    $groupId = intval($groupId);
4812
    $sessionCondition = empty($sessionId) ? " AND (session_id = 0 OR session_id IS NULL) " : " AND session_id='".$session_id."'";
4813
4814
    $groupIid = 0;
4815
    if ($groupId) {
4816
        $groupInfo = GroupManager::get_group_properties($groupId);
4817
        $groupIid = $groupInfo['iid'];
4818
    }
4819
4820
    $sql = "SELECT id, url, title
4821
            FROM $work_table
4822
            WHERE
4823
                c_id = $courseId AND
4824
                active IN (0, 1) AND
4825
                url LIKE '/%' AND
4826
                post_group_id = $groupIid
4827
                $sessionCondition";
4828
    $res = Database::query($sql);
4829
    while ($folder = Database::fetch_array($res)) {
4830
        $title = empty($folder['title']) ? basename($folder['url']) : $folder['title'];
4831
        $folders[$folder['id']] = $title;
4832
    }
4833
4834
    return build_work_move_to_selector($folders, $path, $item_id);
4835
}
4836
4837
/**
4838
 * @param int $workId
4839
 * @return string
4840
 */
4841
function showStudentList($workId)
4842
{
4843
    $columnModel = array(
4844
        array(
4845
            'name' => 'student',
4846
            'index' => 'student',
4847
            'width' => '350px',
4848
            'align' => 'left',
4849
            'sortable' => 'false',
4850
        ),
4851
        array(
4852
            'name' => 'works',
4853
            'index' => 'works',
4854
            'align' => 'center',
4855
            'sortable' => 'false',
4856
        ),
4857
    );
4858
    $token = null;
4859
4860
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_student_list_overview&work_id='.$workId.'&'.api_get_cidreq();
4861
4862
    $columns = array(
4863
        get_lang('Students'),
4864
        get_lang('Works')
4865
    );
4866
4867
    $order = api_is_western_name_order() ? 'firstname' : 'lastname';
4868
    $params = array(
4869
        'autowidth' => 'true',
4870
        'height' => 'auto',
4871
        'rowNum' => 5,
4872
        'sortname' => $order,
4873
        'sortorder' => 'asc'
4874
    );
4875
4876
    $html = '<script>
4877
    $(function() {
4878
        '.Display::grid_js('studentList', $url, $columns, $columnModel, $params, array(), null, true).'
4879
        $("#workList").jqGrid(
4880
            "navGrid",
4881
            "#studentList_pager",
4882
            { edit: false, add: false, del: false },
4883
            { height:280, reloadAfterSubmit:false }, // edit options
4884
            { height:280, reloadAfterSubmit:false }, // add options
4885
            { width:500 } // search options
4886
        );
4887
    });
4888
    </script>';
4889
    $html .= Display::grid_html('studentList');
4890
    return $html;
4891
}
4892
4893
/**
4894
 * @param string $courseCode
4895
 * @param int $sessionId
4896
 * @param int $groupId
4897
 * @param int $start
4898
 * @param int $limit
4899
 * @param string $sidx
4900
 * @param string $sord
4901
 * @param $getCount
4902
 * @return array|int
4903
 */
4904
function getWorkUserList($courseCode, $sessionId, $groupId, $start, $limit, $sidx, $sord, $getCount = false)
4905
{
4906
    if (!empty($groupId)) {
4907
        $userList = GroupManager::get_users(
4908
            $groupId,
4909
            false,
4910
            $start,
4911
            $limit,
4912
            $getCount,
4913
            null,
4914
            $sidx,
4915
            $sord
4916
        );
4917
    } else {
4918
        $limitString = null;
4919 View Code Duplication
        if (!empty($start) && !empty($limit)) {
4920
            $start = intval($start);
4921
            $limit = intval($limit);
4922
            $limitString = " LIMIT $start, $limit";
4923
        }
4924
4925
        $orderBy = null;
4926
4927
        if (!empty($sidx) && !empty($sord)) {
4928
            if (in_array($sidx, array('firstname', 'lastname'))) {
4929
                $orderBy = "ORDER BY $sidx $sord";
4930
            }
4931
        }
4932
4933
        if (empty($sessionId)) {
4934
            $userList = CourseManager::get_user_list_from_course_code(
4935
                $courseCode,
4936
                $sessionId,
4937
                $limitString,
4938
                $orderBy,
4939
                STUDENT,
4940
                $getCount
4941
            );
4942
        } else {
4943
            $userList = CourseManager::get_user_list_from_course_code(
4944
                $courseCode,
4945
                $sessionId,
4946
                $limitString,
4947
                $orderBy,
4948
                0,
4949
                $getCount
4950
            );
4951
        }
4952
4953
        if ($getCount == false) {
4954
            $userList = array_keys($userList);
4955
        }
4956
    }
4957
    return $userList;
4958
}
4959
4960
/**
4961
 * @param int $workId
4962
 * @param string $courseCode
4963
 * @param int $sessionId
4964
 * @param int $groupId
4965
 * @param int $start
4966
 * @param int $limit
4967
 * @param int $sidx
4968
 * @param string $sord
4969
 * @param bool $getCount
4970
 * @return array|int
4971
 */
4972
function getWorkUserListData(
4973
    $workId,
4974
    $courseCode,
4975
    $sessionId,
4976
    $groupId,
4977
    $start,
4978
    $limit,
4979
    $sidx,
4980
    $sord,
4981
    $getCount = false
4982
) {
4983
    $my_folder_data = get_work_data_by_id($workId);
4984
    $workParents = array();
4985
    if (empty($my_folder_data)) {
4986
        $workParents = getWorkList($workId, $my_folder_data, null);
4987
    }
4988
4989
    $workIdList = array();
4990
    if (!empty($workParents)) {
4991
        foreach ($workParents as $work) {
4992
            $workIdList[] = $work->id;
4993
        }
4994
    }
4995
4996
    $courseInfo = api_get_course_info($courseCode);
4997
4998
    $userList = getWorkUserList(
4999
        $courseCode,
5000
        $sessionId,
5001
        $groupId,
5002
        $start,
5003
        $limit,
5004
        $sidx,
5005
        $sord,
5006
        $getCount
5007
    );
5008
5009
    if ($getCount) {
5010
        return $userList;
5011
    }
5012
    $results = array();
5013
    if (!empty($userList)) {
5014
        foreach ($userList as $userId) {
0 ignored issues
show
Bug introduced by
The expression $userList of type array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5015
            $user = api_get_user_info($userId);
5016
            $link = api_get_path(WEB_CODE_PATH).'work/student_work.php?'.api_get_cidreq().'&studentId='.$user['user_id'];
5017
            $url = Display::url(api_get_person_name($user['firstname'], $user['lastname']), $link);
5018
            $userWorks = 0;
5019
            if (!empty($workIdList)) {
5020
                $userWorks = getUniqueStudentAttempts(
5021
                    $workIdList,
5022
                    $groupId,
5023
                    $courseInfo['real_id'],
5024
                    $sessionId,
5025
                    $user['user_id']
5026
                );
5027
            }
5028
            $works = $userWorks." / ".count($workParents);
5029
            $results[] = array(
5030
                'student' => $url,
5031
                'works' => Display::url($works, $link),
5032
            );
5033
        }
5034
    }
5035
5036
    return $results;
5037
}
5038
5039
/**
5040
 * @param int $id
5041
 * @param array $course_info
5042
 * @param bool $isCorrection
5043
 *
5044
 * @return bool
5045
 */
5046
function downloadFile($id, $course_info, $isCorrection)
5047
{
5048
    return getFile($id, $course_info, true, $isCorrection);
5049
}
5050
5051
/**
5052
 * @param int $id
5053
 * @param array $course_info
5054
 * @param bool $download
5055
 * @param bool $isCorrection
5056
 *
5057
 * @return bool
5058
 */
5059
function getFile($id, $course_info, $download = true, $isCorrection = false)
5060
{
5061
    $file = getFileContents($id, $course_info, 0, $isCorrection);
5062
    if (!empty($file) && is_array($file)) {
5063
        return DocumentManager::file_send_for_download(
5064
            $file['path'],
5065
            $download,
5066
            $file['title']
5067
        );
5068
    }
5069
5070
    return false;
5071
}
5072
5073
5074
/**
5075
 * Get the file contents for an assigment
5076
 * @param int $id
5077
 * @param array $course_info
5078
 * @param int Session ID
5079
 * @param $correction
5080
 *
5081
 * @return array|bool
5082
 */
5083
function getFileContents($id, $course_info, $sessionId = 0, $correction = false)
5084
{
5085
    $id = intval($id);
5086
    if (empty($course_info) || empty($id)) {
5087
        return false;
5088
    }
5089
    if (empty($sessionId)) {
5090
        $sessionId = api_get_session_id();
5091
    }
5092
5093
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5094
5095
    if (!empty($course_info['real_id'])) {
5096
        $sql = 'SELECT *
5097
                FROM '.$table.'
5098
                WHERE c_id = '.$course_info['real_id'].' AND id = "'.$id.'"';
5099
        $result = Database::query($sql);
5100
        if ($result && Database::num_rows($result)) {
5101
            $row = Database::fetch_array($result, 'ASSOC');
5102
5103
            if ($correction) {
5104
                $row['url'] = $row['url_correction'];
5105
            }
5106
5107
            if (empty($row['url'])) {
5108
                return false;
5109
            }
5110
5111
            $full_file_name = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'.$row['url'];
5112
5113
            $item_info = api_get_item_property_info(
5114
                api_get_course_int_id(),
5115
                'work',
5116
                $row['id'],
5117
                $sessionId
5118
            );
5119
5120
            if (empty($item_info)) {
5121
                return false;
5122
            }
5123
5124
            allowOnlySubscribedUser(
5125
                api_get_user_id(),
5126
                $row['parent_id'],
5127
                $course_info['real_id']
5128
            );
5129
5130
            /*
5131
            field show_score in table course :
5132
                0 =>    New documents are visible for all users
5133
                1 =>    New documents are only visible for the teacher(s)
5134
            field visibility in table item_property :
5135
                0 => eye closed, invisible for all students
5136
                1 => eye open
5137
            field accepted in table c_student_publication :
5138
                0 => eye closed, invisible for all students
5139
                1 => eye open
5140
            ( We should have visibility == accepted, otherwise there is an
5141
            inconsistency in the Database)
5142
            field value in table c_course_setting :
5143
                0 => Allow learners to delete their own publications = NO
5144
                1 => Allow learners to delete their own publications = YES
5145
5146
            +------------------+-------------------------+------------------------+
5147
            |Can download work?| doc visible for all = 0 | doc visible for all = 1|
5148
            +------------------+-------------------------+------------------------+
5149
            |  visibility = 0  | editor only             | editor only            |
5150
            |                  |                         |                        |
5151
            +------------------+-------------------------+------------------------+
5152
            |  visibility = 1  | editor                  | editor                 |
5153
            |                  | + owner of the work     | + any student          |
5154
            +------------------+-------------------------+------------------------+
5155
            (editor = teacher + admin + anybody with right api_is_allowed_to_edit)
5156
            */
5157
5158
            $work_is_visible = $item_info['visibility'] == 1 && $row['accepted'] == 1;
5159
            $doc_visible_for_all = $course_info['show_score'] == 1;
5160
5161
            $is_editor = api_is_allowed_to_edit(true, true, true);
5162
            $student_is_owner_of_work = user_is_author($row['id'], $row['user_id']);
5163
5164
            if ($is_editor ||
5165
                $student_is_owner_of_work ||
5166
                ($doc_visible_for_all && $work_is_visible)
5167
            ) {
5168
                $title = $row['title'];
5169
                if ($correction) {
5170
                    $title = $row['title_correction'];
5171
                }
5172
                if (array_key_exists('filename', $row) && !empty($row['filename'])) {
5173
                    $title = $row['filename'];
5174
                }
5175
5176
                $title = str_replace(' ', '_', $title);
5177
5178
                if ($correction == false) {
5179
                    $userInfo = api_get_user_info($row['user_id']);
5180
                    if ($userInfo) {
5181
                        $date = api_get_local_time($row['sent_date']);
5182
                        $date = str_replace(array(':', '-', ' '), '_', $date);
5183
                        $title = $date.'_'.$userInfo['username'].'_'.$title;
5184
                    }
5185
                }
5186
5187
                if (Security::check_abs_path(
5188
                    $full_file_name,
5189
                    api_get_path(SYS_COURSE_PATH).api_get_course_path().'/')
5190
                ) {
5191
                    Event::event_download($title);
5192
5193
                    return array(
5194
                        'path' => $full_file_name,
5195
                        'title' => $title,
5196
                        'title_correction' => $row['title_correction']
5197
                    );
5198
                }
5199
            }
5200
        }
5201
    }
5202
5203
    return false;
5204
}
5205
5206
/**
5207
 * @param int $userId
5208
 * @param array $courseInfo
5209
 * @param string $format
5210
 * @return bool
5211
 */
5212
function exportAllWork($userId, $courseInfo, $format = 'pdf')
5213
{
5214
    $userInfo = api_get_user_info($userId);
5215
    if (empty($userInfo) || empty($courseInfo)) {
5216
        return false;
5217
    }
5218
5219
    $workPerUser = getWorkPerUser($userId);
5220
5221
    switch ($format) {
5222
        case 'pdf':
5223
            if (!empty($workPerUser)) {
5224
                $pdf = new PDF();
5225
5226
                $content = null;
5227
                foreach ($workPerUser as $work) {
5228
                    $work = $work['work'];
5229
                    foreach ($work->user_results as $userResult) {
5230
                        $content .= $userResult['title'];
5231
                        // No need to use api_get_local_time()
5232
                        $content .= $userResult['sent_date'];
5233
                        $content .= $userResult['qualification'];
5234
                        $content .= $userResult['description'];
5235
                    }
5236
                }
5237
5238
                if (!empty($content)) {
5239
                    $pdf->content_to_pdf(
5240
                        $content,
5241
                        null,
5242
                        api_replace_dangerous_char($userInfo['complete_name']),
5243
                        $courseInfo['code']
5244
                    );
5245
                }
5246
            }
5247
            break;
5248
    }
5249
}
5250
5251
/**
5252
 * @param int $workId
5253
 * @param array $courseInfo
5254
 * @param int $sessionId
5255
 * @param string $format
5256
 * @return bool
5257
 */
5258
function exportAllStudentWorkFromPublication(
5259
    $workId,
5260
    $courseInfo,
5261
    $sessionId,
5262
    $format = 'pdf'
5263
) {
5264
    if (empty($courseInfo)) {
5265
        return false;
5266
    }
5267
5268
    $workData = get_work_data_by_id($workId);
5269
5270
    if (empty($workData)) {
5271
        return false;
5272
    }
5273
5274
    $assignment = get_work_assignment_by_id($workId);
5275
5276
    $courseCode = $courseInfo['code'];
5277
    $header = get_lang('Course').': '.$courseInfo['title'];
5278
    $teachers = CourseManager::get_teacher_list_from_course_code_to_string(
5279
        $courseCode
5280
    );
5281
5282
    if (!empty($sessionId)) {
5283
        $sessionInfo = api_get_session_info($sessionId);
5284
        if (!empty($sessionInfo)) {
5285
            $header .= ' - '.$sessionInfo['name'];
5286
            $header .= '<br />'.$sessionInfo['description'];
5287
            $teachers = SessionManager::getCoachesByCourseSessionToString(
5288
                $sessionId,
5289
                $courseInfo['real_id']
5290
            );
5291
        }
5292
    }
5293
5294
    $header .= '<br />'.get_lang('Teachers').': '.$teachers.'<br />';
5295
    $header .= '<br />'.get_lang('Date').': '.api_get_local_time().'<br />';
5296
    $header .= '<br />'.get_lang('WorkName').': '.$workData['title'].'<br />';
5297
5298
    $content = null;
5299
    $expiresOn = null;
5300
5301
    if (!empty($assignment) && isset($assignment['expires_on'])) {
5302
        $content .= '<br /><strong>'.get_lang('ExpirationDate').'</strong>: '.api_get_local_time($assignment['expires_on']);
5303
        $expiresOn = api_get_local_time($assignment['expires_on']);
5304
    }
5305
5306
    if (!empty($workData['description'])) {
5307
        $content .= '<br /><strong>'.get_lang('Description').'</strong>: '.$workData['description'];
5308
    }
5309
5310
    $workList = get_work_user_list(null, null, null, null, $workId);
5311
5312
    switch ($format) {
5313
        case 'pdf':
5314
            if (!empty($workList)) {
5315
5316
                $table = new HTML_Table(array('class' => 'data_table'));
5317
                $headers = array(
5318
                    get_lang('Name'),
5319
                    get_lang('User'),
5320
                    get_lang('HandOutDateLimit'),
5321
                    get_lang('SentDate'),
5322
                    get_lang('FileName'),
5323
                    get_lang('Score'),
5324
                    get_lang('Feedback')
5325
                );
5326
5327
                $column = 0;
5328
                foreach ($headers as $header) {
5329
                    $table->setHeaderContents(0, $column, $header);
5330
                    $column++;
5331
                }
5332
5333
                $row = 1;
5334
5335
                //$pdf->set_custom_header($header);
5336
                foreach ($workList as $work) {
5337
                    $content .= '<hr />';
5338
                    // getWorkComments need c_id
5339
                    $work['c_id'] = $courseInfo['real_id'];
5340
5341
                    //$content .= get_lang('Date').': '.api_get_local_time($work['sent_date_from_db']).'<br />';
5342
                    $score = null;
5343
                    if (!empty($work['qualification_only'])) {
5344
                        $score = $work['qualification_only'];
5345
                    }
5346
5347
                    $comments = getWorkComments($work);
5348
5349
                    $feedback = null;
5350
                    if (!empty($comments)) {
5351
                        $content .= '<h4>'.get_lang('Feedback').': </h4>';
5352
                        foreach ($comments as $comment) {
5353
                            $feedback .= get_lang('User').': '.$comment['complete_name'].
5354
                                '<br />';
5355
                            $feedback .= $comment['comment'].'<br />';
5356
                        }
5357
                    }
5358
                    $table->setCellContents($row, 0, strip_tags($workData['title']));
5359
                    $table->setCellContents($row, 1, strip_tags($work['fullname']));
5360
                    $table->setCellContents($row, 2, $expiresOn);
5361
                    $table->setCellContents($row, 3, api_get_local_time($work['sent_date_from_db']));
5362
                    $table->setCellContents($row, 4, strip_tags($work['title']));
5363
                    $table->setCellContents($row, 5, $score);
5364
                    $table->setCellContents($row, 6, $feedback);
5365
5366
                    $row++;
5367
                }
5368
5369
                $content = $table->toHtml();
5370
5371
                if (!empty($content)) {
5372
                    $params = array(
5373
                        'filename' => $workData['title'].'_'.api_get_local_time(),
5374
                        'pdf_title' => api_replace_dangerous_char($workData['title']),
5375
                        'course_code' => $courseInfo['code'],
5376
                        'add_signatures' => false
5377
                    );
5378
                    $pdf = new PDF('A4', null, $params);
5379
                    $pdf->html_to_pdf_with_template($content);
5380
                }
5381
                exit;
5382
            }
5383
            break;
5384
    }
5385
}
5386
5387
/**
5388
 * Downloads all user files per user
5389
 * @param int $userId
5390
 * @param array $courseInfo
5391
 * @return bool
5392
 */
5393
function downloadAllFilesPerUser($userId, $courseInfo)
5394
{
5395
    $userInfo = api_get_user_info($userId);
5396
5397
    if (empty($userInfo) || empty($courseInfo)) {
5398
        return false;
5399
    }
5400
5401
    $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
5402
    $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/';
5403
5404
    $zip = new PclZip($tempZipFile);
5405
5406
    $workPerUser = getWorkPerUser($userId);
5407
5408
    if (!empty($workPerUser)) {
5409
        $files = array();
5410
        foreach ($workPerUser as $work) {
5411
            $work = $work['work'];
5412
            foreach ($work->user_results as $userResult) {
5413
                if (empty($userResult['url']) || empty($userResult['contains_file'])) {
5414
                    continue;
5415
                }
5416
                $data = getFileContents($userResult['id'], $courseInfo);
5417
                if (!empty($data) && isset($data['path'])) {
5418
                    $files[basename($data['path'])] = array(
5419
                        'title' => $data['title'],
5420
                        'path' => $data['path']
5421
                    );
5422
                }
5423
            }
5424
        }
5425
5426
        if (!empty($files)) {
5427
            Session::write('files', $files);
5428
            foreach ($files as $data) {
5429
                $zip->add(
5430
                    $data['path'],
5431
                    PCLZIP_OPT_REMOVE_PATH,
5432
                    $coursePath,
5433
                    PCLZIP_CB_PRE_ADD,
5434
                    'preAddAllWorkStudentCallback'
5435
                );
5436
            }
5437
        }
5438
5439
        // Start download of created file
5440
        $name = basename(api_replace_dangerous_char($userInfo['complete_name'])).'.zip';
5441
        Event::event_download($name.'.zip (folder)');
5442 View Code Duplication
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
5443
            DocumentManager::file_send_for_download($tempZipFile, true, $name);
5444
            @unlink($tempZipFile);
5445
            exit;
5446
        }
5447
    }
5448
    exit;
5449
}
5450
5451
/**
5452
 * @param $p_event
5453
 * @param array $p_header
5454
 * @return int
5455
 */
5456 View Code Duplication
function preAddAllWorkStudentCallback($p_event, &$p_header)
5457
{
5458
    $files = Session::read('files');
5459
    if (isset($files[basename($p_header['stored_filename'])])) {
5460
        $p_header['stored_filename'] = $files[basename($p_header['stored_filename'])]['title'];
5461
        return 1;
5462
    }
5463
    return 0;
5464
}
5465
5466
/**
5467
 * Get all work created by a user
5468
 * @param int $user_id
5469
 * @param int $courseId
5470
 * @param int $sessionId
5471
 * @return array
5472
 */
5473
function getWorkCreatedByUser($user_id, $courseId, $sessionId)
5474
{
5475
    $items = api_get_item_property_list_by_tool_by_user(
5476
        $user_id,
5477
        'work',
5478
        $courseId,
5479
        $sessionId
5480
    );
5481
5482
    $list = array();
5483 View Code Duplication
    if (!empty($items)) {
5484
        foreach ($items as $work) {
5485
            $item = get_work_data_by_id(
5486
                $work['ref'],
5487
                $courseId,
5488
                $sessionId
5489
            );
5490
            if (!empty($item)) {
5491
                $list[] = array(
5492
                    $item['title'],
5493
                    api_get_local_time($work['insert_date']),
5494
                    api_get_local_time($work['lastedit_date'])
5495
                );
5496
            }
5497
        }
5498
    }
5499
5500
    return $list;
5501
}
5502
5503
/**
5504
 * @param array $courseInfo
5505
 * @param int $workId
5506
 * @return bool
5507
 */
5508
function protectWork($courseInfo, $workId)
5509
{
5510
    $userId = api_get_user_id();
5511
    $groupId = api_get_group_id();
5512
    $sessionId = api_get_session_id();
5513
    $workData = get_work_data_by_id($workId);
5514
5515
    if (empty($workData) || empty($courseInfo)) {
5516
        api_not_allowed(true);
5517
    }
5518
5519
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
5520
        return true;
5521
    }
5522
5523
    $workId = $workData['id'];
5524
5525
    if ($workData['active'] != 1) {
5526
        api_not_allowed(true);
5527
    }
5528
5529
    $visibility = api_get_item_visibility($courseInfo, 'work', $workId, $sessionId);
5530
5531
    if ($visibility != 1) {
5532
        api_not_allowed(true);
5533
    }
5534
5535
    allowOnlySubscribedUser($userId, $workId, $courseInfo['real_id']);
5536
    $groupInfo = GroupManager::get_group_properties($groupId);
5537
5538
    if (!empty($groupId)) {
5539
        $showWork = GroupManager::user_has_access(
5540
            $userId,
5541
            $groupInfo['iid'],
5542
            GroupManager::GROUP_TOOL_WORK
5543
        );
5544
        if (!$showWork) {
5545
            api_not_allowed(true);
5546
        }
5547
    }
5548
}
5549
5550
/**
5551
 * @param array $courseInfo
5552
 * @param array $work
5553
 */
5554
function deleteCorrection($courseInfo, $work)
5555
{
5556
    if (isset($work['url_correction']) && !empty($work['url_correction']) && isset($work['iid'])) {
5557
        $id = $work['iid'];
5558
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5559
        $sql = "UPDATE $table SET
5560
                    url_correction = '',
5561
                    title_correction = ''
5562
                WHERE iid = $id";
5563
        Database::query($sql);
5564
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
5565
        if (file_exists($coursePath.$work['url_correction'])) {
5566
            if (Security::check_abs_path($coursePath.$work['url_correction'], $coursePath)) {
5567
                unlink($coursePath.$work['url_correction']);
5568
            }
5569
        }
5570
    }
5571
}
5572