Passed
Push — master ( 49c89f...65060b )
by Julito
10:01
created

getWorkListTeacher()   F

Complexity

Conditions 17
Paths 160

Size

Total Lines 178
Code Lines 110

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 110
c 0
b 0
f 0
nc 160
nop 6
dl 0
loc 178
rs 3.7733

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 Chamilo\CourseBundle\Entity\CStudentPublication;
5
use ChamiloSession as Session;
6
7
/**
8
 *  @package chamilo.work
9
 *
10
 *  @author Thomas, Hugues, Christophe - original version
11
 *  @author Patrick Cool <[email protected]>, Ghent University -
12
 * ability for course admins to specify wether uploaded documents are visible or invisible by default.
13
 *  @author Roan Embrechts, code refactoring and virtual course support
14
 *  @author Frederic Vauthier, directories management
15
 *  @author Julio Montoya <[email protected]> BeezNest 2011 LOTS of bug fixes
16
 *
17
 *  @todo   this lib should be convert in a static class and moved to main/inc/lib
18
 */
19
20
/**
21
 * Displays action links (for admins, authorized groups members and authorized students).
22
 *
23
 * @param   int Whether to show tool options
24
 * @param   int Whether to show upload form option
25
 * @param bool $isTutor
26
 */
27
function displayWorkActionLinks($id, $action, $isTutor)
28
{
29
    $id = $my_back_id = intval($id);
30
    if ($action == 'list') {
31
        $my_back_id = 0;
32
    }
33
34
    $output = '';
35
    $origin = api_get_origin();
36
37
    if (!empty($id)) {
38
        $output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&id='.$my_back_id.'">'.
39
            Display::return_icon('back.png', get_lang('BackToWorksList'), '', ICON_SIZE_MEDIUM).
40
            '</a>';
41
    }
42
43
    if (($isTutor || api_is_allowed_to_edit(null, true)) &&
44
        $origin != 'learnpath'
45
    ) {
46
        // Create dir
47
        if (empty($id)) {
48
            $output .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&action=create_dir">';
49
            $output .= Display::return_icon(
50
                'new_work.png',
51
                get_lang('CreateAssignment'),
52
                '',
53
                ICON_SIZE_MEDIUM
54
            );
55
            $output .= '</a>';
56
        }
57
    }
58
59
    if (api_is_allowed_to_edit(null, true) && $origin != 'learnpath' && $action == 'list') {
60
        $output .= '<a id="open-view-list" href="#">'.
61
            Display::return_icon(
62
                'listwork.png',
63
                get_lang('ViewStudents'),
64
                '',
65
                ICON_SIZE_MEDIUM
66
            ).
67
            '</a>';
68
    }
69
70
    if ($output != '') {
71
        echo '<div class="actions">';
72
        echo $output;
73
        echo '</div>';
74
    }
75
}
76
77
/**
78
 * @param string $path
79
 * @param int    $courseId
80
 *
81
 * @return array
82
 */
83
function get_work_data_by_path($path, $courseId = 0)
84
{
85
    $path = Database::escape_string($path);
86
    $courseId = intval($courseId);
87
    if (empty($courseId)) {
88
        $courseId = api_get_course_int_id();
89
    }
90
91
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
92
    $sql = "SELECT *  FROM $table
93
            WHERE url = '$path' AND c_id = $courseId ";
94
    $result = Database::query($sql);
95
    $return = [];
96
    if (Database::num_rows($result)) {
97
        $return = Database::fetch_array($result, 'ASSOC');
98
    }
99
100
    return $return;
101
}
102
103
/**
104
 * @param int $id
105
 * @param int $courseId
106
 * @param int $sessionId
107
 *
108
 * @return array
109
 */
110
function get_work_data_by_id($id, $courseId = 0, $sessionId = 0)
111
{
112
    $id = intval($id);
113
    $courseId = intval($courseId);
114
    if (empty($courseId)) {
115
        $courseId = api_get_course_int_id();
116
    }
117
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
118
119
    $sessionCondition = '';
120
    if (!empty($sessionId)) {
121
        $sessionCondition = api_get_session_condition($sessionId, true);
122
    }
123
124
    $sql = "SELECT * FROM $table
125
            WHERE
126
                id = $id AND c_id = $courseId
127
                $sessionCondition";
128
    $result = Database::query($sql);
129
    $work = [];
130
    if (Database::num_rows($result)) {
131
        $work = Database::fetch_array($result, 'ASSOC');
132
        if (empty($work['title'])) {
133
            $work['title'] = basename($work['url']);
134
        }
135
        $work['download_url'] = api_get_path(WEB_CODE_PATH).'work/download.php?id='.$work['id'].'&'.api_get_cidreq();
136
        $work['view_url'] = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$work['id'].'&'.api_get_cidreq();
137
        $work['show_url'] = api_get_path(WEB_CODE_PATH).'work/show_file.php?id='.$work['id'].'&'.api_get_cidreq();
138
        $work['show_content'] = '';
139
        if ($work['contains_file']) {
140
            $fileInfo = pathinfo($work['title']);
141
            if (is_array($fileInfo) &&
142
                !empty($fileInfo['extension']) &&
143
                in_array($fileInfo['extension'], ['jpg', 'png', 'gif'])
144
            ) {
145
                $work['show_content'] = '<img src="'.$work['show_url'].'"/>';
146
            }
147
        }
148
149
        $fieldValue = new ExtraFieldValue('work');
150
        $work['extra'] = $fieldValue->getAllValuesForAnItem(
151
            $id,
152
            true
153
        );
154
    }
155
156
    return $work;
157
}
158
159
/**
160
 * @param int $user_id
161
 * @param int $work_id
162
 *
163
 * @return int
164
 */
165
function get_work_count_by_student($user_id, $work_id)
166
{
167
    $user_id = intval($user_id);
168
    $work_id = intval($work_id);
169
    $course_id = api_get_course_int_id();
170
    $session_id = api_get_session_id();
171
    $sessionCondition = api_get_session_condition($session_id);
172
173
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
174
    $sql = "SELECT COUNT(*) as count
175
            FROM  $table
176
            WHERE
177
                c_id = $course_id AND
178
                parent_id = $work_id AND
179
                user_id = $user_id AND
180
                active IN (0, 1)
181
                $sessionCondition";
182
    $result = Database::query($sql);
183
    $return = 0;
184
    if (Database::num_rows($result)) {
185
        $return = Database::fetch_row($result, 'ASSOC');
186
        $return = intval($return[0]);
187
    }
188
189
    return $return;
190
}
191
192
/**
193
 * @param int $id
194
 * @param int $courseId
195
 *
196
 * @return array
197
 */
198
function get_work_assignment_by_id($id, $courseId = 0)
199
{
200
    $courseId = intval($courseId);
201
    if (empty($courseId)) {
202
        $courseId = api_get_course_int_id();
203
    }
204
    $id = intval($id);
205
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
206
    $sql = "SELECT * FROM $table
207
            WHERE c_id = $courseId AND publication_id = $id";
208
    $result = Database::query($sql);
209
    $return = [];
210
    if (Database::num_rows($result)) {
211
        $return = Database::fetch_array($result, 'ASSOC');
212
    }
213
214
    return $return;
215
}
216
217
/**
218
 * @param int    $id
219
 * @param array  $my_folder_data
220
 * @param string $add_in_where_query
221
 * @param int    $course_id
222
 * @param int    $session_id
223
 *
224
 * @return array
225
 */
226
function getWorkList($id, $my_folder_data, $add_in_where_query = null, $course_id = 0, $session_id = 0)
227
{
228
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
229
230
    $course_id = $course_id ? $course_id : api_get_course_int_id();
231
    $session_id = $session_id ? $session_id : api_get_session_id();
232
    $condition_session = api_get_session_condition($session_id);
233
    $group_id = api_get_group_id();
234
235
    $groupIid = 0;
236
    if ($group_id) {
237
        $groupInfo = GroupManager::get_group_properties($group_id);
238
        if ($groupInfo) {
239
            $groupIid = $groupInfo['iid'];
240
        }
241
    }
242
243
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
244
    $linkInfo = GradebookUtils::isResourceInCourseGradebook(
245
        api_get_course_id(),
246
        3,
247
        $id,
248
        api_get_session_id()
249
    );
250
251
    if ($linkInfo) {
252
        $workInGradeBookLinkId = $linkInfo['id'];
253
        if ($workInGradeBookLinkId) {
254
            if ($is_allowed_to_edit) {
255
                if (intval($my_folder_data['qualification']) == 0) {
256
                    echo Display::return_message(
257
                        get_lang('MaxWeightNeedToBeProvided'),
258
                        'warning'
259
                    );
260
                }
261
            }
262
        }
263
    }
264
265
    $contains_file_query = '';
266
    // Get list from database
267
    if ($is_allowed_to_edit) {
268
        $active_condition = ' active IN (0, 1)';
269
        $sql = "SELECT * FROM $work_table
270
                WHERE
271
                    c_id = $course_id
272
                    $add_in_where_query
273
                    $condition_session AND
274
                    $active_condition AND
275
                    (parent_id = 0)
276
                    $contains_file_query AND 
277
                    post_group_id = $groupIid
278
                ORDER BY sent_date DESC";
279
    } else {
280
        if (!empty($group_id)) {
281
            // set to select only messages posted by the user's group
282
            $group_query = " WHERE c_id = $course_id AND post_group_id = $groupIid";
283
            $subdirs_query = " AND parent_id = 0";
284
        } else {
285
            $group_query = " WHERE c_id = $course_id AND (post_group_id = '0' OR post_group_id is NULL) ";
286
            $subdirs_query = " AND parent_id = 0";
287
        }
288
        //@todo how we can active or not an assignment?
289
        $active_condition = ' AND active IN (1, 0)';
290
        $sql = "SELECT * FROM  $work_table
291
                $group_query
292
                $subdirs_query
293
                $add_in_where_query
294
                $active_condition
295
                $condition_session
296
                ORDER BY title";
297
    }
298
299
    $work_parents = [];
300
301
    $sql_result = Database::query($sql);
302
    if (Database::num_rows($sql_result)) {
303
        while ($work = Database::fetch_object($sql_result)) {
304
            if ($work->parent_id == 0) {
305
                $work_parents[] = $work;
306
            }
307
        }
308
    }
309
310
    return $work_parents;
311
}
312
313
/**
314
 * @param int $userId
315
 * @param int $courseId
316
 * @param int $sessionId
317
 *
318
 * @return array
319
 */
320
function getWorkPerUser($userId, $courseId = 0, $sessionId = 0)
321
{
322
    $works = getWorkList(null, null, null, $courseId, $sessionId);
323
    $result = [];
324
    if (!empty($works)) {
325
        foreach ($works as $workData) {
326
            $workId = $workData->id;
327
            $result[$workId]['work'] = $workData;
328
            $result[$workId]['work']->user_results = get_work_user_list(
329
                0,
330
                100,
331
                null,
332
                null,
333
                $workId,
334
                null,
335
                $userId,
336
                false,
337
                $courseId,
338
                $sessionId
339
            );
340
        }
341
    }
342
343
    return $result;
344
}
345
346
/**
347
 * @param int $workId
348
 * @param int $groupId
349
 * @param int $course_id
350
 * @param int $sessionId
351
 *
352
 * @return mixed
353
 */
354
function getUniqueStudentAttemptsTotal($workId, $groupId, $course_id, $sessionId)
355
{
356
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
357
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
358
    $course_id = intval($course_id);
359
    $workId = intval($workId);
360
    $sessionId = intval($sessionId);
361
    $groupId = intval($groupId);
362
    $sessionCondition = api_get_session_condition(
363
        $sessionId,
364
        true,
365
        false,
366
        'w.session_id'
367
    );
368
369
    $groupIid = 0;
370
    if ($groupId) {
371
        $groupInfo = GroupManager::get_group_properties($groupId);
372
        $groupIid = $groupInfo['iid'];
373
    }
374
375
    $sql = "SELECT count(DISTINCT u.user_id)
376
            FROM $work_table w
377
            INNER JOIN $user_table u
378
            ON w.user_id = u.user_id
379
            WHERE
380
                w.c_id = $course_id
381
                $sessionCondition AND
382
                w.parent_id = $workId AND
383
                w.post_group_id = $groupIid AND
384
                w.active IN (0, 1)
385
            ";
386
387
    $res_document = Database::query($sql);
388
    $rowCount = Database::fetch_row($res_document);
389
390
    return $rowCount[0];
391
}
392
393
/**
394
 * @param mixed $workId
395
 * @param int   $groupId
396
 * @param int   $course_id
397
 * @param int   $sessionId
398
 * @param int   $userId       user id to filter
399
 * @param array $onlyUserList only parse this user list
400
 *
401
 * @return mixed
402
 */
403
function getUniqueStudentAttempts(
404
    $workId,
405
    $groupId,
406
    $course_id,
407
    $sessionId,
408
    $userId = null,
409
    $onlyUserList = []
410
) {
411
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
412
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
413
414
    $course_id = intval($course_id);
415
    $workCondition = null;
416
    if (is_array($workId)) {
417
        $workId = array_map('intval', $workId);
418
        $workId = implode("','", $workId);
419
        $workCondition = " w.parent_id IN ('".$workId."') AND";
420
    } else {
421
        $workId = intval($workId);
422
        $workCondition = " w.parent_id = ".$workId." AND";
423
    }
424
425
    $sessionId = intval($sessionId);
426
    $groupId = intval($groupId);
427
    $studentCondition = null;
428
429
    if (!empty($onlyUserList)) {
430
        $onlyUserList = array_map('intval', $onlyUserList);
431
        $studentCondition = "AND u.user_id IN ('".implode("', '", $onlyUserList)."') ";
432
    } else {
433
        if (empty($userId)) {
434
            return 0;
435
        }
436
    }
437
438
    $groupIid = 0;
439
    if ($groupId) {
440
        $groupInfo = GroupManager::get_group_properties($groupId);
441
        $groupIid = $groupInfo['iid'];
442
    }
443
444
    $sessionCondition = api_get_session_condition(
445
        $sessionId,
446
        true,
447
        false,
448
        'w.session_id'
449
    );
450
451
    $sql = "SELECT count(*) FROM (
452
                SELECT count(*), w.parent_id
453
                FROM $work_table w
454
                INNER JOIN $user_table u
455
                ON w.user_id = u.user_id
456
                WHERE
457
                    w.filetype = 'file' AND
458
                    w.c_id = $course_id
459
                    $sessionCondition AND
460
                    $workCondition
461
                    w.post_group_id = $groupIid AND
462
                    w.active IN (0, 1) $studentCondition
463
                ";
464
    if (!empty($userId)) {
465
        $userId = intval($userId);
466
        $sql .= " AND u.user_id = ".$userId;
467
    }
468
    $sql .= " GROUP BY u.user_id, w.parent_id) as t";
469
    $result = Database::query($sql);
470
    $row = Database::fetch_row($result);
471
472
    return $row[0];
473
}
474
475
/**
476
 * Shows the work list (student view).
477
 *
478
 * @return string
479
 */
480
function showStudentWorkGrid()
481
{
482
    $courseInfo = api_get_course_info();
483
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_student&'.api_get_cidreq();
484
485
    $columns = [
486
        get_lang('Type'),
487
        get_lang('Title'),
488
        get_lang('HandOutDateLimit'),
489
        get_lang('Feedback'),
490
        get_lang('LastUpload'),
491
    ];
492
493
    $columnModel = [
494
        ['name' => 'type', 'index' => 'type', 'width' => '30', 'align' => 'center', 'sortable' => 'false'],
495
        ['name' => 'title', 'index' => 'title', 'width' => '250', 'align' => 'left'],
496
        ['name' => 'expires_on', 'index' => 'expires_on', 'width' => '80', 'align' => 'center', 'sortable' => 'false'],
497
        ['name' => 'feedback', 'index' => 'feedback', 'width' => '80', 'align' => 'center', 'sortable' => 'false'],
498
        ['name' => 'last_upload', 'index' => 'feedback', 'width' => '125', 'align' => 'center', 'sortable' => 'false'],
499
    ];
500
501
    if ($courseInfo['show_score'] == 0) {
502
        $columnModel[] = [
503
            'name' => 'others',
504
            'index' => 'others',
505
            'width' => '80',
506
            'align' => 'left',
507
            'sortable' => 'false',
508
        ];
509
        $columns[] = get_lang('Others');
510
    }
511
512
    $params = [
513
        'autowidth' => 'true',
514
        'height' => 'auto',
515
    ];
516
517
    $html = '<script>
518
        $(function() {
519
            '.Display::grid_js('workList', $url, $columns, $columnModel, $params, [], null, true).'
520
        });
521
    </script>';
522
523
    $html .= Display::grid_html('workList');
524
525
    return $html;
526
}
527
528
/**
529
 * Shows the work list (teacher view).
530
 *
531
 * @return string
532
 */
533
function showTeacherWorkGrid()
534
{
535
    $columnModel = [
536
        ['name' => 'type', 'index' => 'type', 'width' => '35', 'align' => 'center', 'sortable' => 'false'],
537
        ['name' => 'title', 'index' => 'title', 'width' => '300', 'align' => 'left', 'wrap_cell' => "true"],
538
        ['name' => 'sent_date', 'index' => 'sent_date', 'width' => '125', 'align' => 'center'],
539
        ['name' => 'expires_on', 'index' => 'expires_on', 'width' => '125', 'align' => 'center'],
540
        ['name' => 'amount', 'index' => 'amount', 'width' => '110', 'align' => 'center', 'sortable' => 'false'],
541
        ['name' => 'actions', 'index' => 'actions', 'width' => '110', 'align' => 'left', 'sortable' => 'false'],
542
    ];
543
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_teacher&'.api_get_cidreq();
544
    $deleteUrl = api_get_path(WEB_AJAX_PATH).'work.ajax.php?a=delete_work&'.api_get_cidreq();
545
546
    $columns = [
547
        get_lang('Type'),
548
        get_lang('Title'),
549
        get_lang('SentDate'),
550
        get_lang('HandOutDateLimit'),
551
        get_lang('AmountSubmitted'),
552
        get_lang('Actions'),
553
    ];
554
555
    $params = [
556
        'multiselect' => true,
557
        'autowidth' => 'true',
558
        'height' => 'auto',
559
    ];
560
561
    $html = '<script>
562
    $(function() {
563
        '.Display::grid_js('workList', $url, $columns, $columnModel, $params, [], null, true).'
564
        $("#workList").jqGrid(
565
            "navGrid",
566
            "#workList_pager",
567
            { edit: false, add: false, del: true },
568
            { height:280, reloadAfterSubmit:false }, // edit options
569
            { height:280, reloadAfterSubmit:false }, // add options
570
            { reloadAfterSubmit:false, url: "'.$deleteUrl.'" }, // del options
571
            { width:500 } // search options
572
        );
573
    });
574
    </script>';
575
    $html .= Display::grid_html('workList');
576
577
    return $html;
578
}
579
580
/**
581
 * Builds the form thats enables the user to
582
 * select a directory to browse/upload in
583
 * This function has been copied from the document/document.inc.php library.
584
 *
585
 * @param array  $folders
586
 * @param string $curdirpath
587
 * @param string $group_dir
588
 *
589
 * @return string html form
590
 */
591
// TODO: This function is a candidate for removal, it is not used anywhere.
592
function build_work_directory_selector($folders, $curdirpath, $group_dir = '')
593
{
594
    $form = '<form name="selector" action="'.api_get_self().'?'.api_get_cidreq().'" method="POST">';
595
    $form .= get_lang('CurrentDirectory').' 
596
             <select name="curdirpath" onchange="javascript: document.selector.submit();">';
597
    //group documents cannot be uploaded in the root
598
    if ($group_dir == '') {
599
        $form .= '<option value="/">/ ('.get_lang('Root').')</option>';
600
        if (is_array($folders)) {
601
            foreach ($folders as $folder) {
602
                $selected = ($curdirpath == $folder) ? ' selected="selected"' : '';
603
                $form .= '<option'.$selected.' value="'.$folder.'">'.$folder.'</option>'."\n";
604
            }
605
        }
606
    } else {
607
        foreach ($folders as $folder) {
608
            $selected = ($curdirpath == $folder) ? ' selected="selected"' : '';
609
            $display_folder = substr($folder, strlen($group_dir));
610
            $display_folder = ($display_folder == '') ? '/ ('.get_lang('Root').')' : $display_folder;
611
            $form .= '<option'.$selected.' value="'.$folder.'">'.$display_folder.'</option>'."\n";
612
        }
613
    }
614
615
    $form .= '</select>';
616
    $form .= '<noscript><input type="submit" name="change_path" value="'.get_lang('Ok').'" /></noscript>';
617
    $form .= '</form>';
618
619
    return $form;
620
}
621
622
/**
623
 * Builds the form that enables the user to
624
 * move a document from one directory to another
625
 * This function has been copied from the document/document.inc.php library.
626
 *
627
 * @param array  $folders
628
 * @param string $curdirpath
629
 * @param string $move_file
630
 * @param string $group_dir
631
 *
632
 * @return string html form
633
 */
634
function build_work_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
635
{
636
    $course_id = api_get_course_int_id();
637
    $move_file = intval($move_file);
638
    $tbl_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
639
    $sql = "SELECT title, url FROM $tbl_work
640
            WHERE c_id = $course_id AND id ='".$move_file."'";
641
    $result = Database::query($sql);
642
    $row = Database::fetch_array($result, 'ASSOC');
643
    $title = empty($row['title']) ? basename($row['url']) : $row['title'];
644
645
    $form = new FormValidator(
646
        'move_to_form',
647
        'post',
648
        api_get_self().'?'.api_get_cidreq().'&curdirpath='.Security::remove_XSS($curdirpath)
649
    );
650
651
    $form->addHeader(get_lang('MoveFile').' - '.Security::remove_XSS($title));
652
    $form->addHidden('item_id', $move_file);
653
    $form->addHidden('action', 'move_to');
654
655
    // Group documents cannot be uploaded in the root
656
    if ($group_dir == '') {
657
        if (is_array($folders)) {
658
            foreach ($folders as $fid => $folder) {
659
                //you cannot move a file to:
660
                //1. current directory
661
                //2. inside the folder you want to move
662
                //3. inside a subfolder of the folder you want to move
663
                if (($curdirpath != $folder) &&
664
                    ($folder != $move_file) &&
665
                    (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')
666
                ) {
667
                    $options[$fid] = $folder;
668
                }
669
            }
670
        }
671
    } else {
672
        if ($curdirpath != '/') {
673
            $form .= '<option value="0">/ ('.get_lang('Root').')</option>';
674
        }
675
        foreach ($folders as $fid => $folder) {
676
            if (($curdirpath != $folder) && ($folder != $move_file) &&
677
                (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')
678
            ) {
679
                //cannot copy dir into his own subdir
680
                $display_folder = substr($folder, strlen($group_dir));
681
                $display_folder = ($display_folder == '') ? '/ ('.get_lang('Root').')' : $display_folder;
682
                //$form .= '<option value="'.$fid.'">'.$display_folder.'</option>'."\n";
683
                $options[$fid] = $display_folder;
684
            }
685
        }
686
    }
687
688
    $form->addSelect('move_to_id', get_lang('Select'), $options);
689
    $form->addButtonSend(get_lang('MoveFile'), 'move_file_submit');
690
691
    return $form->returnForm();
692
}
693
694
/**
695
 * creates a new directory trying to find a directory name
696
 * that doesn't already exist.
697
 *
698
 * @author Hugues Peeters <[email protected]>
699
 * @author Bert Vanderkimpen
700
 * @author Yannick Warnier <[email protected]> Adaptation for work tool
701
 *
702
 * @param string $workDir        Base work dir (.../work)
703
 * @param string $desiredDirName complete path of the desired name
704
 *
705
 * @return string actual directory name if it succeeds, boolean false otherwise
706
 */
707
function create_unexisting_work_directory($workDir, $desiredDirName)
708
{
709
    $counter = 0;
710
    $workDir = (substr($workDir, -1, 1) == '/' ? $workDir : $workDir.'/');
711
    $checkDirName = $desiredDirName;
712
    while (file_exists($workDir.$checkDirName)) {
713
        $counter++;
714
        $checkDirName = $desiredDirName.$counter;
715
    }
716
717
    if (@mkdir($workDir.$checkDirName, api_get_permissions_for_new_directories())) {
718
        return $checkDirName;
719
    } else {
720
        return false;
721
    }
722
}
723
724
/**
725
 * Delete a work-tool directory.
726
 *
727
 * @param int $id work directory id to delete
728
 *
729
 * @return int -1 on error
730
 */
731
function deleteDirWork($id)
732
{
733
    $locked = api_resource_is_locked_by_gradebook($id, LINK_STUDENTPUBLICATION);
734
735
    if ($locked == true) {
736
        echo Display::return_message(get_lang('ResourceLockedByGradebook'), 'warning');
737
738
        return false;
739
    }
740
741
    $_course = api_get_course_info();
742
    $id = intval($id);
743
    $work_data = get_work_data_by_id($id);
744
745
    if (empty($work_data)) {
746
        return false;
747
    }
748
749
    $base_work_dir = api_get_path(SYS_COURSE_PATH).$_course['path'].'/work';
750
    $work_data_url = $base_work_dir.$work_data['url'];
751
    $check = Security::check_abs_path($work_data_url.'/', $base_work_dir.'/');
752
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
753
    $TSTDPUBASG = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
754
    $t_agenda = Database::get_course_table(TABLE_AGENDA);
755
    $course_id = api_get_course_int_id();
756
    $sessionId = api_get_session_id();
757
758
    if (!empty($work_data['url'])) {
759
        if ($check) {
760
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
761
            if (!empty($consideredWorkingTime)) {
762
                $fieldValue = new ExtraFieldValue('work');
763
                $resultExtra = $fieldValue->getAllValuesForAnItem(
764
                    $work_data['id'],
765
                    true
766
                );
767
768
                $workingTime = null;
769
                foreach ($resultExtra as $field) {
770
                    $field = $field['value'];
771
                    if ($consideredWorkingTime == $field->getField()->getVariable()) {
772
                        $workingTime = $field->getValue();
773
774
                        break;
775
                    }
776
                }
777
778
                $courseUsers = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
779
                if (!empty($workingTime)) {
780
                    foreach ($courseUsers as $user) {
781
                        $userWorks = get_work_user_list(
782
                            0,
783
                            100,
784
                            null,
785
                            null,
786
                            $work_data['id'],
787
                            null,
788
                            $user['user_id'],
789
                            false,
790
                            $course_id,
791
                            $sessionId
792
                        );
793
794
                        if (count($userWorks) != 1) {
795
                            continue;
796
                        }
797
                        Event::eventRemoveVirtualCourseTime($course_id, $user['user_id'], $sessionId, $workingTime);
798
                    }
799
                }
800
            }
801
802
            // Deleting all contents inside the folder
803
            $sql = "UPDATE $table SET active = 2
804
                    WHERE c_id = $course_id AND filetype = 'folder' AND id = $id";
805
            Database::query($sql);
806
807
            $sql = "UPDATE $table SET active = 2
808
                    WHERE c_id = $course_id AND parent_id = $id";
809
            Database::query($sql);
810
811
            $new_dir = $work_data_url.'_DELETED_'.$id;
812
813
            if (api_get_setting('permanently_remove_deleted_files') == 'true') {
814
                my_delete($work_data_url);
815
            } else {
816
                if (file_exists($work_data_url)) {
817
                    rename($work_data_url, $new_dir);
818
                }
819
            }
820
821
            // Gets calendar_id from student_publication_assigment
822
            $sql = "SELECT add_to_calendar FROM $TSTDPUBASG
823
                    WHERE c_id = $course_id AND publication_id = $id";
824
            $res = Database::query($sql);
825
            $calendar_id = Database::fetch_row($res);
826
827
            // delete from agenda if it exists
828
            if (!empty($calendar_id[0])) {
829
                $sql = "DELETE FROM $t_agenda
830
                        WHERE c_id = $course_id AND id = '".$calendar_id[0]."'";
831
                Database::query($sql);
832
            }
833
            $sql = "DELETE FROM $TSTDPUBASG
834
                    WHERE c_id = $course_id AND publication_id = $id";
835
            Database::query($sql);
836
837
            Skill::deleteSkillsFromItem($id, ITEM_TYPE_STUDENT_PUBLICATION);
838
839
            Event::addEvent(
840
                LOG_WORK_DIR_DELETE,
841
                LOG_WORK_DATA,
842
                [
843
                    'id' => $work_data['id'],
844
                    'url' => $work_data['url'],
845
                    'title' => $work_data['title'],
846
                ],
847
                null,
848
                api_get_user_id(),
849
                api_get_course_int_id(),
850
                $sessionId
851
            );
852
853
            $linkInfo = GradebookUtils::isResourceInCourseGradebook(
854
                api_get_course_id(),
855
                3,
856
                $id,
857
                api_get_session_id()
858
            );
859
            $link_id = $linkInfo['id'];
860
            if ($linkInfo !== false) {
861
                GradebookUtils::remove_resource_from_course_gradebook($link_id);
862
            }
863
864
            return true;
865
        }
866
    }
867
}
868
869
/**
870
 * Get the path of a document in the student_publication table (path relative to the course directory).
871
 *
872
 * @param int $id
873
 *
874
 * @return string Path (or -1 on error)
875
 */
876
function get_work_path($id)
877
{
878
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
879
    $course_id = api_get_course_int_id();
880
    $sql = 'SELECT url FROM '.$table.'
881
            WHERE c_id = '.$course_id.' AND id='.intval($id);
882
    $res = Database::query($sql);
883
    if (Database::num_rows($res)) {
884
        $row = Database::fetch_array($res);
885
886
        return $row['url'];
887
    }
888
889
    return -1;
890
}
891
892
/**
893
 * Update the url of a work in the student_publication table.
894
 *
895
 * @param int    $id        of the work to update
896
 * @param string $new_path  Destination directory where the work has been moved (must end with a '/')
897
 * @param int    $parent_id
898
 *
899
 * @return mixed Int -1 on error, sql query result on success
900
 */
901
function updateWorkUrl($id, $new_path, $parent_id)
902
{
903
    if (empty($id)) {
904
        return -1;
905
    }
906
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
907
    $course_id = api_get_course_int_id();
908
    $id = intval($id);
909
    $parent_id = intval($parent_id);
910
911
    $sql = "SELECT * FROM $table
912
            WHERE c_id = $course_id AND id = $id";
913
    $res = Database::query($sql);
914
    if (Database::num_rows($res) != 1) {
915
        return -1;
916
    } else {
917
        $row = Database::fetch_array($res);
918
        $filename = basename($row['url']);
919
        $new_url = $new_path.$filename;
920
        $new_url = Database::escape_string($new_url);
921
922
        $sql = "UPDATE $table SET
923
                   url = '$new_url',
924
                   parent_id = '$parent_id'
925
                WHERE c_id = $course_id AND id = $id";
926
        $res = Database::query($sql);
927
928
        return $res;
929
    }
930
}
931
932
/**
933
 * Update the url of a dir in the student_publication table.
934
 *
935
 * @param array  $work_data work original data
936
 * @param string $newPath   Example: "folder1"
937
 *
938
 * @return bool
939
 */
940
function updateDirName($work_data, $newPath)
941
{
942
    $course_id = $work_data['c_id'];
943
    $work_id = intval($work_data['iid']);
944
    $oldPath = $work_data['url'];
945
    $originalNewPath = Database::escape_string($newPath);
946
    $newPath = Database::escape_string($newPath);
947
    $newPath = api_replace_dangerous_char($newPath);
948
    $newPath = disable_dangerous_file($newPath);
949
950
    if ($oldPath == '/'.$newPath) {
951
        return true;
952
    }
953
954
    if (!empty($newPath)) {
955
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
956
        $sql = "UPDATE $table SET
957
                    title = '".$originalNewPath."'
958
                WHERE
959
                    c_id = $course_id AND
960
                    iid = $work_id";
961
        Database::query($sql);
962
    }
963
}
964
965
/**
966
 * returns all the javascript that is required for easily
967
 * validation when you create a work
968
 * this goes into the $htmlHeadXtra[] array.
969
 */
970
function to_javascript_work()
971
{
972
    $js = '<script> 
973
        function updateDocumentTitle(value) {
974
            var temp = value.indexOf("/");            
975
            //linux path
976
            if(temp != -1){
977
                temp=value.split("/");
978
            } else {
979
                temp=value.split("\\\");
980
            }
981
            
982
            var fullFilename = temp[temp.length - 1];
983
            var baseFilename = fullFilename;
984
            
985
            // get file extension
986
            var fileExtension = "";
987
            if (fullFilename.match(/\..+/)) {
988
                fileInfo = fullFilename.match(/(.*)\.([^.]+)$/);
989
                if (fileInfo.length > 1) {
990
                    fileExtension = "."+fileInfo[fileInfo.length - 1];
991
                    baseFilename = fileInfo[fileInfo.length - 2];
992
                }
993
            }
994
            
995
            document.getElementById("file_upload").value = baseFilename;
996
            document.getElementById("file_extension").value = fileExtension;                
997
            $("#contains_file_id").attr("value", 1);
998
        }
999
        function setFocus() {
1000
            $("#work_title").focus();
1001
        }
1002
1003
        $(document).ready(function() {
1004
            setFocus();
1005
            var checked = $("#expiry_date").attr("checked");
1006
            if (checked) {
1007
                $("#option2").show();                
1008
            } else {
1009
                $("#option2").hide();                
1010
            }
1011
            
1012
            var checkedEndDate = $("#end_date").attr("checked");            
1013
            if (checkedEndDate) {                
1014
                $("#option3").show();
1015
                $("#ends_on").attr("checked", true);
1016
            } else {
1017
                $("#option3").hide();                
1018
                $("#ends_on").attr("checked", false);
1019
            }
1020
1021
            $("#expiry_date").click(function() {
1022
                $("#option2").toggle();
1023
            });
1024
1025
            $("#end_date").click(function() {
1026
                $("#option3").toggle();
1027
            });
1028
        });
1029
    </script>';
1030
1031
    return $js;
1032
}
1033
1034
/**
1035
 * Gets the id of a student publication with a given path.
1036
 *
1037
 * @param string $path
1038
 *
1039
 * @return true if is found / false if not found
1040
 */
1041
// TODO: The name of this function does not fit with the kind of information it returns.
1042
// Maybe check_work_id() or is_work_id()?
1043
function get_work_id($path)
1044
{
1045
    $TBL_STUDENT_PUBLICATION = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1046
    $TBL_PROP_TABLE = Database::get_course_table(TABLE_ITEM_PROPERTY);
1047
    $course_id = api_get_course_int_id();
1048
    $path = Database::escape_string($path);
1049
1050
    if (api_is_allowed_to_edit()) {
1051
        $sql = "SELECT work.id
1052
                FROM $TBL_STUDENT_PUBLICATION AS work, $TBL_PROP_TABLE AS props
1053
                WHERE
1054
                    props.c_id = $course_id AND
1055
                    work.c_id = $course_id AND
1056
                    props.tool='work' AND
1057
                    work.id=props.ref AND
1058
                    work.url LIKE 'work/".$path."%' AND
1059
                    work.filetype='file' AND
1060
                    props.visibility<>'2'";
1061
    } else {
1062
        $sql = "SELECT work.id
1063
                FROM $TBL_STUDENT_PUBLICATION AS work, $TBL_PROP_TABLE AS props
1064
                WHERE
1065
                    props.c_id = $course_id AND
1066
                    work.c_id = $course_id AND
1067
                    props.tool='work' AND
1068
                    work.id=props.ref AND
1069
                    work.url LIKE 'work/".$path."%' AND
1070
                    work.filetype='file' AND
1071
                    props.visibility<>'2' AND
1072
                    props.lastedit_user_id = '".api_get_user_id()."'";
1073
    }
1074
    $result = Database::query($sql);
1075
    $num_rows = Database::num_rows($result);
1076
1077
    if ($result && $num_rows > 0) {
1078
        return true;
1079
    } else {
1080
        return false;
1081
    }
1082
}
1083
1084
/**
1085
 * @param int $work_id
1086
 * @param int $onlyMeUserId show only my works
1087
 * @param int $notMeUserId  show works from everyone except me
1088
 *
1089
 * @return int
1090
 */
1091
function get_count_work($work_id, $onlyMeUserId = null, $notMeUserId = null)
1092
{
1093
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1094
    $iprop_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1095
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
1096
1097
    $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
1098
    $session_id = api_get_session_id();
1099
    $condition_session = api_get_session_condition(
1100
        $session_id,
1101
        true,
1102
        false,
1103
        'work.session_id'
1104
    );
1105
1106
    $group_id = api_get_group_id();
1107
    $course_info = api_get_course_info();
1108
    $course_id = $course_info['real_id'];
1109
    $work_id = intval($work_id);
1110
1111
    $groupIid = 0;
1112
    if ($group_id) {
1113
        $groupInfo = GroupManager::get_group_properties($group_id);
1114
        $groupIid = $groupInfo['iid'];
1115
    }
1116
1117
    if (!empty($group_id)) {
1118
        // set to select only messages posted by the user's group
1119
        $extra_conditions = " work.post_group_id = '".intval($groupIid)."' ";
1120
    } else {
1121
        $extra_conditions = " (work.post_group_id = '0' or work.post_group_id IS NULL) ";
1122
    }
1123
1124
    if ($is_allowed_to_edit) {
1125
        $extra_conditions .= ' AND work.active IN (0, 1) ';
1126
    } else {
1127
        $extra_conditions .= ' AND work.active IN (0, 1) AND accepted = 1';
1128
        if (isset($course_info['show_score']) && $course_info['show_score'] == 1) {
1129
            $extra_conditions .= " AND work.user_id = ".api_get_user_id()." ";
1130
        } else {
1131
            $extra_conditions .= '';
1132
        }
1133
    }
1134
1135
    $extra_conditions .= " AND parent_id  = ".$work_id."  ";
1136
    $where_condition = null;
1137
    if (!empty($notMeUserId)) {
1138
        $where_condition .= " AND u.user_id <> ".intval($notMeUserId);
1139
    }
1140
1141
    if (!empty($onlyMeUserId)) {
1142
        $where_condition .= " AND u.user_id =  ".intval($onlyMeUserId);
1143
    }
1144
1145
    $sql = "SELECT count(*) as count
1146
            FROM $iprop_table prop
1147
            INNER JOIN $work_table work
1148
            ON (
1149
                prop.ref = work.id AND
1150
                prop.c_id = $course_id AND
1151
                prop.tool='work' AND
1152
                prop.visibility <> 2 AND
1153
                work.c_id = $course_id
1154
            )
1155
            INNER JOIN $user_table u 
1156
            ON (work.user_id = u.user_id)
1157
            WHERE $extra_conditions $where_condition $condition_session";
1158
1159
    $result = Database::query($sql);
1160
1161
    $users_with_work = 0;
1162
    if (Database::num_rows($result)) {
1163
        $result = Database::fetch_array($result);
1164
        $users_with_work = $result['count'];
1165
    }
1166
1167
    return $users_with_work;
1168
}
1169
1170
/**
1171
 * @param int    $start
1172
 * @param int    $limit
1173
 * @param string $column
1174
 * @param string $direction
1175
 * @param string $where_condition
1176
 * @param bool   $getCount
1177
 *
1178
 * @return array
1179
 */
1180
function getWorkListStudent(
1181
    $start,
1182
    $limit,
1183
    $column,
1184
    $direction,
1185
    $where_condition,
1186
    $getCount = false
1187
) {
1188
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1189
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1190
    $courseInfo = api_get_course_info();
1191
    $course_id = $courseInfo['real_id'];
1192
    $session_id = api_get_session_id();
1193
    $condition_session = api_get_session_condition($session_id);
1194
    $group_id = api_get_group_id();
1195
    $userId = api_get_user_id();
1196
1197
    $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
1198
        api_get_user_id(),
1199
        $courseInfo
1200
    );
1201
1202
    if (!in_array($direction, ['asc', 'desc'])) {
1203
        $direction = 'desc';
1204
    }
1205
    if (!empty($where_condition)) {
1206
        $where_condition = ' AND '.$where_condition;
1207
    }
1208
1209
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1210
    $start = intval($start);
1211
    $limit = intval($limit);
1212
1213
    $groupIid = 0;
1214
    if ($group_id) {
1215
        $groupInfo = GroupManager::get_group_properties($group_id);
1216
        $groupIid = $groupInfo['iid'];
1217
    }
1218
    $groupIid = (int) $groupIid;
1219
1220
    // Get list from database
1221
    if (!empty($groupIid)) {
1222
        $group_query = " WHERE w.c_id = $course_id AND post_group_id = $groupIid";
1223
        $subdirs_query = "AND parent_id = 0";
1224
    } else {
1225
        $group_query = " WHERE w.c_id = $course_id AND (post_group_id = '0' or post_group_id is NULL)  ";
1226
        $subdirs_query = "AND parent_id = 0";
1227
    }
1228
1229
    $active_condition = ' AND active IN (1, 0)';
1230
1231
    if ($getCount) {
1232
        $select = "SELECT count(w.id) as count ";
1233
    } else {
1234
        $select = "SELECT w.*, a.expires_on, expires_on, ends_on, enable_qualification ";
1235
    }
1236
1237
    $sql = "$select
1238
            FROM $workTable w
1239
            LEFT JOIN $workTableAssignment a
1240
            ON (a.publication_id = w.id AND a.c_id = w.c_id)
1241
                $group_query
1242
                $subdirs_query
1243
                $active_condition
1244
                $condition_session
1245
                $where_condition
1246
            ";
1247
1248
    $sql .= " ORDER BY $column $direction ";
1249
1250
    if (!empty($start) && !empty($limit)) {
1251
        $sql .= " LIMIT $start, $limit";
1252
    }
1253
1254
    $result = Database::query($sql);
1255
1256
    if ($getCount) {
1257
        $row = Database::fetch_array($result);
1258
1259
        return $row['count'];
1260
    }
1261
1262
    $works = [];
1263
    $url = api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq();
1264
    if ($isDrhOfCourse) {
1265
        $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq();
1266
    }
1267
1268
    $urlOthers = api_get_path(WEB_CODE_PATH).'work/work_list_others.php?'.api_get_cidreq().'&id=';
1269
    while ($work = Database::fetch_array($result, 'ASSOC')) {
1270
        $isSubscribed = userIsSubscribedToWork($userId, $work['id'], $course_id);
1271
        if ($isSubscribed == false) {
1272
            continue;
1273
        }
1274
1275
        $visibility = api_get_item_visibility($courseInfo, 'work', $work['id'], $session_id);
1276
1277
        if ($visibility != 1) {
1278
            continue;
1279
        }
1280
1281
        $work['type'] = Display::return_icon('work.png');
1282
        $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1283
1284
        if (empty($work['title'])) {
1285
            $work['title'] = basename($work['url']);
1286
        }
1287
1288
        $whereCondition = " AND u.user_id = ".intval($userId);
1289
1290
        $workList = get_work_user_list(
1291
            0,
1292
            1000,
1293
            null,
1294
            null,
1295
            $work['id'],
1296
            $whereCondition
1297
        );
1298
1299
        $count = getTotalWorkComment($workList, $courseInfo);
1300
        $lastWork = getLastWorkStudentFromParentByUser($userId, $work, $courseInfo);
1301
1302
        if (!is_null($count) && !empty($count)) {
1303
            $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$lastWork['id'].'&'.api_get_cidreq();
1304
1305
            $feedback = '&nbsp;'.Display::url(
1306
                Display::returnFontAwesomeIcon('comments-o'),
1307
                $urlView,
1308
                ['title' => get_lang('View')]
1309
            );
1310
1311
            $work['feedback'] = ' '.Display::label($count.' '.get_lang('Feedback'), 'info').$feedback;
1312
        }
1313
1314
        if (!empty($lastWork)) {
1315
            $work['last_upload'] = (!empty($lastWork['qualification'])) ? $lastWork['qualification_rounded'].' - ' : '';
1316
            $work['last_upload'] .= api_get_local_time($lastWork['sent_date']);
1317
        }
1318
1319
        $work['title'] = Display::url($work['title'], $url.'&id='.$work['id']);
1320
        $work['others'] = Display::url(
1321
            Display::return_icon('group.png', get_lang('Others')),
1322
            $urlOthers.$work['id']
1323
        );
1324
        $works[] = $work;
1325
    }
1326
1327
    return $works;
1328
}
1329
1330
/**
1331
 * @param int    $start
1332
 * @param int    $limit
1333
 * @param string $column
1334
 * @param string $direction
1335
 * @param string $where_condition
1336
 * @param bool   $getCount
1337
 *
1338
 * @return array
1339
 */
1340
function getWorkListTeacher(
1341
    $start,
1342
    $limit,
1343
    $column,
1344
    $direction,
1345
    $where_condition,
1346
    $getCount = false
1347
) {
1348
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1349
    $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1350
1351
    $courseInfo = api_get_course_info();
1352
    $course_id = api_get_course_int_id();
1353
    $session_id = api_get_session_id();
1354
    $condition_session = api_get_session_condition($session_id);
1355
    $group_id = api_get_group_id();
1356
    $groupIid = 0;
1357
    if ($group_id) {
1358
        $groupInfo = GroupManager::get_group_properties($group_id);
1359
        $groupIid = $groupInfo['iid'];
1360
    }
1361
    $groupIid = (int) $groupIid;
1362
1363
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
1364
    if (!in_array($direction, ['asc', 'desc'])) {
1365
        $direction = 'desc';
1366
    }
1367
    if (!empty($where_condition)) {
1368
        $where_condition = ' AND '.$where_condition;
1369
    }
1370
1371
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1372
    $start = intval($start);
1373
    $limit = intval($limit);
1374
    $works = [];
1375
1376
    // Get list from database
1377
    if ($is_allowed_to_edit) {
1378
        $active_condition = ' active IN (0, 1)';
1379
        if ($getCount) {
1380
            $select = " SELECT count(w.id) as count";
1381
        } else {
1382
            $select = " SELECT w.*, a.expires_on, expires_on, ends_on, enable_qualification ";
1383
        }
1384
        $sql = " $select
1385
                FROM $workTable w
1386
                LEFT JOIN $workTableAssignment a
1387
                ON (a.publication_id = w.id AND a.c_id = w.c_id)
1388
                WHERE
1389
                    w.c_id = $course_id
1390
                    $condition_session AND
1391
                    $active_condition AND
1392
                    parent_id = 0 AND
1393
                    post_group_id = $groupIid
1394
                    $where_condition
1395
                ORDER BY $column $direction
1396
                LIMIT $start, $limit";
1397
1398
        $result = Database::query($sql);
1399
1400
        if ($getCount) {
1401
            $row = Database::fetch_array($result);
1402
1403
            return $row['count'];
1404
        }
1405
1406
        $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq();
1407
        $blockEdition = api_get_configuration_value('block_student_publication_edition');
1408
        while ($work = Database::fetch_array($result, 'ASSOC')) {
1409
            $workId = $work['id'];
1410
            $work['type'] = Display::return_icon('work.png');
1411
            $work['expires_on'] = empty($work['expires_on']) ? null : api_get_local_time($work['expires_on']);
1412
1413
            $countUniqueAttempts = getUniqueStudentAttemptsTotal(
1414
                $workId,
1415
                $group_id,
1416
                $course_id,
1417
                $session_id
1418
            );
1419
1420
            $totalUsers = getStudentSubscribedToWork(
1421
                $workId,
1422
                $course_id,
1423
                $group_id,
1424
                $session_id,
1425
                true
1426
            );
1427
1428
            $work['amount'] = Display::label(
1429
                $countUniqueAttempts.'/'.
1430
                $totalUsers,
1431
                'success'
1432
            );
1433
1434
            $visibility = api_get_item_visibility($courseInfo, 'work', $workId, $session_id);
1435
1436
            if ($visibility == 1) {
1437
                $icon = 'visible.png';
1438
                $text = get_lang('Visible');
1439
                $action = 'invisible';
1440
                $class = '';
1441
            } else {
1442
                $icon = 'invisible.png';
1443
                $text = get_lang('Invisible');
1444
                $action = 'visible';
1445
                $class = 'muted';
1446
            }
1447
1448
            $visibilityLink = Display::url(
1449
                Display::return_icon($icon, $text, [], ICON_SIZE_SMALL),
1450
                api_get_path(WEB_CODE_PATH).'work/work.php?id='.$workId.'&action='.$action.'&'.api_get_cidreq()
1451
            );
1452
1453
            if (empty($work['title'])) {
1454
                $work['title'] = basename($work['url']);
1455
            }
1456
            $work['title'] = Display::url($work['title'], $url.'&id='.$workId, ['class' => $class]);
1457
            $work['title'] .= ' '.Display::label(get_count_work($work['id']), 'success');
1458
            $work['sent_date'] = api_get_local_time($work['sent_date']);
1459
1460
            if ($blockEdition && !api_is_platform_admin()) {
1461
                $editLink = '';
1462
            } else {
1463
                $editLink = Display::url(
1464
                    Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL),
1465
                    api_get_path(WEB_CODE_PATH).'work/edit_work.php?id='.$workId.'&'.api_get_cidreq()
1466
                );
1467
            }
1468
1469
            $correctionLink = '&nbsp;'.Display::url(
1470
                Display::return_icon('upload_package.png', get_lang('UploadCorrections'), '', ICON_SIZE_SMALL),
1471
                api_get_path(WEB_CODE_PATH).'work/upload_corrections.php?'.api_get_cidreq().'&id='.$workId
1472
            ).'&nbsp;';
1473
1474
            if ($countUniqueAttempts > 0) {
1475
                $downloadLink = Display::url(
1476
                    Display::return_icon(
1477
                        'save_pack.png',
1478
                        get_lang('Save'),
1479
                        [],
1480
                        ICON_SIZE_SMALL
1481
                    ),
1482
                    api_get_path(WEB_CODE_PATH).'work/downloadfolder.inc.php?id='.$workId.'&'.api_get_cidreq()
1483
                );
1484
            } else {
1485
                $downloadLink = Display::url(
1486
                    Display::return_icon(
1487
                        'save_pack_na.png',
1488
                        get_lang('Save'),
1489
                        [],
1490
                        ICON_SIZE_SMALL
1491
                    ),
1492
                    '#'
1493
                );
1494
            }
1495
            // Remove Delete Work Button from action List
1496
            // Because removeXSS "removes" the onClick JS Event to do the action (See model.ajax.php - Line 1639)
1497
            // But still can use the another jqgrid button to remove works (trash icon)
1498
            //
1499
            // $deleteUrl = api_get_path(WEB_CODE_PATH).'work/work.php?id='.$workId.'&action=delete_dir&'.api_get_cidreq();
1500
            // $deleteLink = '<a href="#" onclick="showConfirmationPopup(this, \'' . $deleteUrl . '\' ) " >' .
1501
            //     Display::return_icon(
1502
            //         'delete.png',
1503
            //         get_lang('Delete'),
1504
            //         [],
1505
            //         ICON_SIZE_SMALL
1506
            //     ) . '</a>';
1507
1508
            if (!api_is_allowed_to_edit()) {
1509
                // $deleteLink = null;
1510
                $editLink = null;
1511
            }
1512
            $work['actions'] = $visibilityLink.$correctionLink.$downloadLink.$editLink;
1513
            $works[] = $work;
1514
        }
1515
    }
1516
1517
    return $works;
1518
}
1519
1520
/**
1521
 * @param int    $start
1522
 * @param int    $limit
1523
 * @param string $column
1524
 * @param string $direction
1525
 * @param int    $workId
1526
 * @param int    $studentId
1527
 * @param string $whereCondition
1528
 * @param bool   $getCount
1529
 *
1530
 * @return array
1531
 */
1532
function get_work_user_list_from_documents(
1533
    $start,
1534
    $limit,
1535
    $column,
1536
    $direction,
1537
    $workId,
1538
    $studentId = null,
1539
    $whereCondition = '',
1540
    $getCount = false
1541
) {
1542
    if ($getCount) {
1543
        $select1 = " SELECT count(u.user_id) as count ";
1544
        $select2 = " SELECT count(u.user_id) as count ";
1545
    } else {
1546
        $select1 = " SELECT DISTINCT 
1547
                        u.firstname, 
1548
                        u.lastname, 
1549
                        u.user_id, 
1550
                        w.title,
1551
                        w.parent_id, 
1552
                        w.document_id document_id, 
1553
                        w.id, qualification, 
1554
                        qualificator_id, 
1555
                        w.sent_date,
1556
                        w.contains_file,
1557
                        w.url
1558
                    ";
1559
        $select2 = " SELECT DISTINCT 
1560
                        u.firstname, u.lastname,
1561
                        u.user_id, 
1562
                        d.title, 
1563
                        w.parent_id, 
1564
                        d.id document_id, 
1565
                        0, 
1566
                        0, 
1567
                        0,
1568
                        w.sent_date,
1569
                        w.contains_file,
1570
                        w.url                        
1571
                    ";
1572
    }
1573
1574
    $documentTable = Database::get_course_table(TABLE_DOCUMENT);
1575
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1576
    $workRelDocument = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
1577
    $userTable = Database::get_main_table(TABLE_MAIN_USER);
1578
1579
    $courseId = api_get_course_int_id();
1580
    $sessionId = api_get_session_id();
1581
1582
    if (empty($studentId)) {
1583
        $studentId = api_get_user_id();
1584
    }
1585
    $studentId = intval($studentId);
1586
    $workId = intval($workId);
1587
1588
    $userCondition = " AND u.user_id = $studentId ";
1589
    $sessionCondition = api_get_session_condition($sessionId, true, false, 'w.session_id');
1590
    $workCondition = " AND w_rel.work_id = $workId";
1591
    $workParentCondition = " AND w.parent_id = $workId";
1592
1593
    $sql = "(
1594
                $select1 FROM $userTable u
1595
                INNER JOIN $workTable w
1596
                ON (u.user_id = w.user_id AND w.active IN (0, 1) AND w.filetype = 'file')
1597
                WHERE
1598
                    w.c_id = $courseId
1599
                    $userCondition
1600
                    $sessionCondition
1601
                    $whereCondition
1602
                    $workParentCondition
1603
            ) UNION (
1604
                $select2 FROM $workTable w
1605
                INNER JOIN $workRelDocument w_rel
1606
                ON (w_rel.work_id = w.id AND w.active IN (0, 1) AND w_rel.c_id = w.c_id)
1607
                INNER JOIN $documentTable d
1608
                ON (w_rel.document_id = d.id AND d.c_id = w.c_id)
1609
                INNER JOIN $userTable u ON (u.user_id = $studentId)
1610
                WHERE
1611
                    w.c_id = $courseId
1612
                    $workCondition
1613
                    $sessionCondition AND
1614
                    d.id NOT IN (
1615
                        SELECT w.document_id id
1616
                        FROM $workTable w
1617
                        WHERE
1618
                            user_id = $studentId AND
1619
                            c_id = $courseId AND
1620
                            filetype = 'file' AND
1621
                            active IN (0, 1)
1622
                            $sessionCondition
1623
                            $workParentCondition
1624
                    )
1625
            )";
1626
1627
    $start = intval($start);
1628
    $limit = intval($limit);
1629
1630
    $direction = in_array(strtolower($direction), ['desc', 'asc']) ? $direction : 'desc';
1631
    $column = Database::escape_string($column);
1632
1633
    if ($getCount) {
1634
        $result = Database::query($sql);
1635
        $result = Database::fetch_array($result);
1636
1637
        return $result['count'];
1638
    }
1639
1640
    $sql .= " ORDER BY $column $direction";
1641
    $sql .= " LIMIT $start, $limit";
1642
1643
    $result = Database::query($sql);
1644
1645
    $currentUserId = api_get_user_id();
1646
    $work_data = get_work_data_by_id($workId);
1647
    $qualificationExists = false;
1648
1649
    if (!empty($work_data['qualification']) && intval($work_data['qualification']) > 0) {
1650
        $qualificationExists = true;
1651
    }
1652
1653
    $urlAdd = api_get_path(WEB_CODE_PATH).'work/upload_from_template.php?'.api_get_cidreq();
1654
    $urlEdit = api_get_path(WEB_CODE_PATH).'work/edit.php?'.api_get_cidreq();
1655
    $urlDelete = api_get_path(WEB_CODE_PATH).'work/work_list.php?action=delete&'.api_get_cidreq();
1656
    $urlView = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq();
1657
    $urlDownload = api_get_path(WEB_CODE_PATH).'work/download.php?'.api_get_cidreq();
1658
1659
    $editIcon = Display::return_icon('edit.png', get_lang('Edit'));
1660
    $addIcon = Display::return_icon('add.png', get_lang('Add'));
1661
    $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'));
1662
    $viewIcon = Display::return_icon('default.png', get_lang('View'));
1663
    $saveIcon = Display::return_icon(
1664
        'save.png',
1665
        get_lang('Save'),
1666
        [],
1667
        ICON_SIZE_SMALL
1668
    );
1669
    $allowEdition = api_get_course_setting('student_delete_own_publication') == 1;
1670
1671
    $workList = [];
1672
    while ($row = Database::fetch_array($result, 'ASSOC')) {
1673
        $userId = $row['user_id'];
1674
        $documentId = $row['document_id'];
1675
        $itemId = $row['id'];
1676
        $addLinkShowed = false;
1677
1678
        if (empty($documentId)) {
1679
            $url = $urlEdit.'&item_id='.$row['id'].'&id='.$workId;
1680
            $editLink = Display::url($editIcon, $url);
1681
            if ($allowEdition != 1) {
1682
                $editLink = null;
1683
            }
1684
        } else {
1685
            $documentToWork = getDocumentToWorkPerUser($documentId, $workId, $courseId, $sessionId, $userId);
1686
1687
            if (empty($documentToWork)) {
1688
                $url = $urlAdd.'&document_id='.$documentId.'&id='.$workId;
1689
                $editLink = Display::url($addIcon, $url);
1690
                $addLinkShowed = true;
1691
            } else {
1692
                $row['title'] = $documentToWork['title'];
1693
                $row['sent_date'] = $documentToWork['sent_date'];
1694
                $newWorkId = $documentToWork['id'];
1695
                $url = $urlEdit.'&item_id='.$newWorkId.'&id='.$workId;
1696
                $editLink = Display::url($editIcon, $url);
1697
1698
                if ($allowEdition != 1) {
1699
                    $editLink = '';
1700
                }
1701
            }
1702
        }
1703
1704
        $downloadLink = '';
1705
        // If URL is present then there's a file to download keep BC.
1706
        if ($row['contains_file'] || !empty($row['url'])) {
1707
            $downloadLink = Display::url($saveIcon, $urlDownload.'&id='.$row['id']).'&nbsp;';
1708
        }
1709
1710
        $viewLink = '';
1711
        if (!empty($itemId)) {
1712
            $viewLink = Display::url($viewIcon, $urlView.'&id='.$itemId);
1713
        }
1714
1715
        $deleteLink = '';
1716
        if ($allowEdition == 1 && !empty($itemId)) {
1717
            $deleteLink = Display::url($deleteIcon, $urlDelete.'&item_id='.$itemId.'&id='.$workId);
1718
        }
1719
1720
        $row['type'] = null;
1721
1722
        if ($qualificationExists) {
1723
            if (empty($row['qualificator_id'])) {
1724
                $status = Display::label(get_lang('NotRevised'), 'warning');
1725
            } else {
1726
                $status = Display::label(get_lang('Revised'), 'success');
1727
            }
1728
            $row['qualificator_id'] = $status;
1729
        }
1730
1731
        if (!empty($row['qualification'])) {
1732
            $row['qualification'] = Display::label($row['qualification'], 'info');
1733
        }
1734
1735
        if (!empty($row['sent_date'])) {
1736
            $row['sent_date'] = Display::dateToStringAgoAndLongDate($row['sent_date']);
1737
        }
1738
1739
        if ($userId == $currentUserId) {
1740
            $row['actions'] = $downloadLink.$viewLink.$editLink.$deleteLink;
1741
        }
1742
1743
        if ($addLinkShowed) {
1744
            $row['qualification'] = '';
1745
            $row['qualificator_id'] = '';
1746
        }
1747
1748
        $workList[] = $row;
1749
    }
1750
1751
    return $workList;
1752
}
1753
1754
/**
1755
 * @param int    $start
1756
 * @param int    $limit
1757
 * @param int    $column
1758
 * @param string $direction
1759
 * @param int    $work_id
1760
 * @param array  $where_condition
1761
 * @param int    $studentId
1762
 * @param bool   $getCount
1763
 * @param int    $courseId
1764
 * @param int    $sessionId
1765
 *
1766
 * @return array
1767
 */
1768
function get_work_user_list(
1769
    $start,
1770
    $limit,
1771
    $column,
1772
    $direction,
1773
    $work_id,
1774
    $where_condition = null,
1775
    $studentId = null,
1776
    $getCount = false,
1777
    $courseId = 0,
1778
    $sessionId = 0
1779
) {
1780
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1781
    $user_table = Database::get_main_table(TABLE_MAIN_USER);
1782
1783
    $session_id = $sessionId ? $sessionId : api_get_session_id();
1784
    $group_id = api_get_group_id();
1785
    $course_info = api_get_course_info();
1786
    $course_info = empty($course_info) ? api_get_course_info_by_id($courseId) : $course_info;
1787
    $course_id = isset($course_info['real_id']) ? $course_info['real_id'] : $courseId;
1788
1789
    $work_id = intval($work_id);
1790
    $column = !empty($column) ? Database::escape_string($column) : 'sent_date';
1791
    $start = intval($start);
1792
    $limit = intval($limit);
1793
1794
    if (!in_array($direction, ['asc', 'desc'])) {
1795
        $direction = 'desc';
1796
    }
1797
1798
    $work_data = get_work_data_by_id($work_id, $courseId, $sessionId);
1799
    $is_allowed_to_edit = api_is_allowed_to_edit() || api_is_coach();
1800
    $condition_session = api_get_session_condition(
1801
        $session_id,
1802
        true,
1803
        false,
1804
        'work.session_id'
1805
    );
1806
    $locked = api_resource_is_locked_by_gradebook(
1807
        $work_id,
1808
        LINK_STUDENTPUBLICATION,
1809
        $course_info['code']
1810
    );
1811
1812
    $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
1813
        api_get_user_id(),
1814
        $course_info
1815
    );
1816
1817
    $groupIid = 0;
1818
    if ($group_id) {
1819
        $groupInfo = GroupManager::get_group_properties($group_id);
1820
        $groupIid = $groupInfo['iid'];
1821
    }
1822
1823
    if (!empty($work_data)) {
1824
        if (!empty($group_id)) {
1825
            $extra_conditions = " work.post_group_id = '".intval($groupIid)."' ";
1826
        // set to select only messages posted by the user's group
1827
        } else {
1828
            $extra_conditions = " (work.post_group_id = '0' OR work.post_group_id is NULL) ";
1829
        }
1830
1831
        if ($is_allowed_to_edit || $isDrhOfCourse) {
1832
            $extra_conditions .= ' AND work.active IN (0, 1) ';
1833
        } else {
1834
            if (isset($course_info['show_score']) &&
1835
                $course_info['show_score'] == 1
1836
            ) {
1837
                $extra_conditions .= " AND (u.user_id = ".api_get_user_id()." AND work.active IN (0, 1)) ";
1838
            } else {
1839
                $extra_conditions .= ' AND work.active IN (0, 1) ';
1840
            }
1841
        }
1842
1843
        $extra_conditions .= " AND parent_id  = ".$work_id." ";
1844
1845
        $select = 'SELECT DISTINCT
1846
                        u.user_id,
1847
                        work.id as id,
1848
                        title as title,
1849
                        description,
1850
                        url,
1851
                        sent_date,
1852
                        contains_file,
1853
                        has_properties,
1854
                        view_properties,
1855
                        qualification,
1856
                        weight,
1857
                        allow_text_assignment,
1858
                        u.firstname,
1859
                        u.lastname,
1860
                        u.username,
1861
                        parent_id,
1862
                        accepted,
1863
                        qualificator_id,
1864
                        url_correction,
1865
                        title_correction
1866
                        ';
1867
        if ($getCount) {
1868
            $select = "SELECT DISTINCT count(u.user_id) as count ";
1869
        }
1870
1871
        $work_assignment = get_work_assignment_by_id($work_id, $courseId);
1872
1873
        if (!empty($studentId)) {
1874
            $where_condition .= " AND u.user_id = ".intval($studentId);
1875
        }
1876
1877
        $sql = " $select
1878
                FROM $work_table work 
1879
                INNER JOIN $user_table u  
1880
                ON (work.user_id = u.user_id)
1881
                WHERE
1882
                    work.c_id = $course_id AND
1883
                    $extra_conditions 
1884
                    $where_condition 
1885
                    $condition_session
1886
                    AND u.status != ".INVITEE."
1887
                ORDER BY $column $direction";
1888
1889
        if (!empty($start) && !empty($limit)) {
1890
            $sql .= " LIMIT $start, $limit";
1891
        }
1892
        $result = Database::query($sql);
1893
        $works = [];
1894
1895
        if ($getCount) {
1896
            $work = Database::fetch_array($result, 'ASSOC');
1897
1898
            return $work['count'];
1899
        }
1900
1901
        $url = api_get_path(WEB_CODE_PATH).'work/';
1902
        $unoconv = api_get_configuration_value('unoconv.binaries');
1903
        $loadingText = addslashes(get_lang('Loading'));
1904
        $uploadedText = addslashes(get_lang('Uploaded'));
1905
        $failsUploadText = addslashes(get_lang('UplNoFileUploaded'));
1906
        $failsUploadIcon = Display::return_icon(
1907
            'closed-circle.png',
1908
            '',
1909
            [],
1910
            ICON_SIZE_TINY
1911
        );
1912
        $saveIcon = Display::return_icon(
1913
            'save.png',
1914
            get_lang('Save'),
1915
            [],
1916
            ICON_SIZE_SMALL
1917
        );
1918
1919
        $correctionIcon = Display::return_icon(
1920
            'check-circle.png',
1921
            get_lang('Correction'),
1922
            null,
1923
            ICON_SIZE_SMALL
1924
        );
1925
1926
        $correctionIconSmall = Display::return_icon(
1927
            'check-circle.png',
1928
            get_lang('Correction'),
1929
            null,
1930
            ICON_SIZE_TINY
1931
        );
1932
1933
        $rateIcon = Display::return_icon(
1934
            'rate_work.png',
1935
            get_lang('CorrectAndRate'),
1936
            [],
1937
            ICON_SIZE_SMALL
1938
        );
1939
1940
        $blockEdition = api_get_configuration_value('block_student_publication_edition');
1941
        $blockScoreEdition = api_get_configuration_value('block_student_publication_score_edition');
1942
1943
        while ($work = Database::fetch_array($result, 'ASSOC')) {
1944
            $item_id = $work['id'];
1945
            // Get the author ID for that document from the item_property table
1946
            $is_author = false;
1947
            $can_read = false;
1948
            $owner_id = $work['user_id'];
1949
1950
            /* Because a bug found when saving items using the api_item_property_update()
1951
               the field $item_property_data['insert_user_id'] is not reliable. */
1952
            if (!$is_allowed_to_edit && $owner_id == api_get_user_id()) {
1953
                $is_author = true;
1954
            }
1955
1956
            if ($course_info['show_score'] == 0) {
1957
                $can_read = true;
1958
            }
1959
1960
            $qualification_exists = false;
1961
            if (!empty($work_data['qualification']) &&
1962
                intval($work_data['qualification']) > 0
1963
            ) {
1964
                $qualification_exists = true;
1965
            }
1966
1967
            $qualification_string = '';
1968
            if ($qualification_exists) {
1969
                if ($work['qualification'] == '') {
1970
                    $qualification_string = Display::label('-');
1971
                } else {
1972
                    $qualification_string = formatWorkScore($work['qualification'], $work_data['qualification']);
1973
                }
1974
            }
1975
1976
            $work['qualification_score'] = $work['qualification'];
1977
            $add_string = '';
1978
            $time_expires = '';
1979
            if (!empty($work_assignment['expires_on'])) {
1980
                $time_expires = api_strtotime(
1981
                    $work_assignment['expires_on'],
1982
                    'UTC'
1983
                );
1984
            }
1985
1986
            if (!empty($work_assignment['expires_on']) &&
1987
                !empty($time_expires) && ($time_expires < api_strtotime($work['sent_date'], 'UTC'))) {
1988
                $add_string = Display::label(get_lang('Expired'), 'important').' - ';
1989
            }
1990
1991
            if (($can_read && $work['accepted'] == '1') ||
1992
                ($is_author && in_array($work['accepted'], ['1', '0'])) ||
1993
                ($is_allowed_to_edit || api_is_drh())
1994
            ) {
1995
                // Firstname, lastname, username
1996
                $work['fullname'] = Display::div(
1997
                    api_get_person_name($work['firstname'], $work['lastname']),
1998
                    ['class' => 'work-name']
1999
                );
2000
                // Title
2001
                $work['title_clean'] = $work['title'];
2002
                $work['title'] = Security::remove_XSS($work['title']);
2003
                if (strlen($work['title']) > 30) {
2004
                    $short_title = substr($work['title'], 0, 27).'...';
2005
                    $work['title'] = Display::span($short_title, ['class' => 'work-title', 'title' => $work['title']]);
2006
                } else {
2007
                    $work['title'] = Display::div($work['title'], ['class' => 'work-title']);
2008
                }
2009
2010
                // Type.
2011
                $work['type'] = DocumentManager::build_document_icon_tag('file', $work['url']);
2012
2013
                // File name.
2014
                $linkToDownload = '';
2015
                // If URL is present then there's a file to download keep BC.
2016
                if ($work['contains_file'] || !empty($work['url'])) {
2017
                    $linkToDownload = '<a href="'.$url.'download.php?id='.$item_id.'&'.api_get_cidreq().'">'.$saveIcon.'</a> ';
2018
                }
2019
2020
                $feedback = '';
2021
                $count = getWorkCommentCount($item_id, $course_info);
2022
                if (!is_null($count) && !empty($count)) {
2023
                    if ($qualification_exists) {
2024
                        $feedback .= ' ';
2025
                    }
2026
2027
                    $feedback .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang(
2028
                            'View'
2029
                        ).'">'.
2030
                    $count.' '.Display::returnFontAwesomeIcon('comments-o').'</a> ';
2031
                }
2032
2033
                $correction = '';
2034
                $hasCorrection = '';
2035
                if (!empty($work['url_correction'])) {
2036
                    $hasCorrection = Display::url(
2037
                        $correctionIcon,
2038
                        api_get_path(WEB_CODE_PATH).'work/download.php?id='.$item_id.'&'.api_get_cidreq().'&correction=1'
2039
                    );
2040
                }
2041
2042
                if ($qualification_exists) {
2043
                    $work['qualification'] = $qualification_string.$feedback;
2044
                } else {
2045
                    $work['qualification'] = $qualification_string.$feedback.$hasCorrection;
2046
                }
2047
2048
                $work['qualification_only'] = $qualification_string;
2049
2050
                // Date.
2051
                $work_date = api_get_local_time($work['sent_date']);
2052
                $date = date_to_str_ago($work['sent_date']).' '.$work_date;
2053
                $work['formatted_date'] = $work_date.' '.$add_string;
2054
                $work['sent_date_from_db'] = $work['sent_date'];
2055
                $work['sent_date'] = '<div class="work-date" title="'.$date.'">'.
2056
                    $add_string.' '.Display::dateToStringAgoAndLongDate($work['sent_date']).'</div>';
2057
                $work['status'] = $hasCorrection;
2058
                $work['has_correction'] = $hasCorrection;
2059
2060
                // Actions.
2061
                $action = '';
2062
                if (api_is_allowed_to_edit()) {
2063
                    if ($blockScoreEdition && !api_is_platform_admin() && !empty($work['qualification_score'])) {
2064
                        $rateLink = '';
2065
                    } else {
2066
                        $rateLink = '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2067
                            $rateIcon.'</a> ';
2068
                    }
2069
                    $action .= $rateLink;
2070
2071
                    if ($unoconv && empty($work['contains_file'])) {
2072
                        $action .= '<a f
2073
                            href="'.$url.'work_list_all.php?'.api_get_cidreq().'&id='.$work_id.'&action=export_to_doc&item_id='.$item_id.'" 
2074
                            title="'.get_lang('ExportToDoc').'" >'.
2075
                            Display::return_icon('export_doc.png', get_lang('ExportToDoc'), [], ICON_SIZE_SMALL).'</a> ';
2076
                    }
2077
2078
                    $alreadyUploaded = '';
2079
                    if (!empty($work['url_correction'])) {
2080
                        $alreadyUploaded = '<br />'.$work['title_correction'].' '.$correctionIconSmall;
2081
                    }
2082
2083
                    $correction = '
2084
                        <form
2085
                        id="file_upload_'.$item_id.'"
2086
                        class="work_correction_file_upload file_upload_small fileinput-button"
2087
                        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"
2088
                        >
2089
                        <div id="progress_'.$item_id.'" class="text-center button-load">
2090
                            '.addslashes(get_lang('ClickOrDropOneFileHere')).'
2091
                            '.Display::return_icon('upload_file.png', get_lang('Correction'), [], ICON_SIZE_TINY).'
2092
                            '.$alreadyUploaded.'
2093
                        </div>
2094
                        <input id="file_'.$item_id.'" type="file" name="file" class="" multiple>
2095
                        </form>
2096
                    ';
2097
2098
                    $correction .= "<script>
2099
                    $(document).ready(function() {
2100
                        $('.work_correction_file_upload').each(function () {
2101
                            $(this).fileupload({
2102
                                dropZone: $(this)
2103
                            });
2104
                        });
2105
                        $('#file_upload_".$item_id."').fileupload({
2106
                            add: function (e, data) {
2107
                                $('#progress_$item_id').html();
2108
                                //$('#file_$item_id').remove();
2109
                                data.context = $('#progress_$item_id').html('$loadingText <br /> <em class=\"fa fa-spinner fa-pulse fa-fw\"></em>');
2110
                                data.submit();
2111
                                $(this).removeClass('hover');
2112
                            },
2113
                            dragover: function (e, data) {
2114
                                $(this).addClass('hover');
2115
                            },
2116
                            done: function (e, data) {
2117
                                if (data._response.result.name) {
2118
                                    $('#progress_$item_id').html('$uploadedText '+data._response.result.result+'<br />'+data._response.result.name);
2119
                                } else {
2120
                                    $('#progress_$item_id').html('$failsUploadText $failsUploadIcon');
2121
                                }
2122
                                $(this).removeClass('hover');
2123
                            }
2124
                        });
2125
                        $('#file_upload_".$item_id."').on('dragleave', function (e) {
2126
                            // dragleave callback implementation
2127
                            $(this).removeClass('hover');
2128
                        });
2129
                    });
2130
                    </script>";
2131
2132
                    if ($locked) {
2133
                        if ($qualification_exists) {
2134
                            $action .= Display::return_icon(
2135
                                'edit_na.png',
2136
                                get_lang('CorrectAndRate'),
2137
                                [],
2138
                                ICON_SIZE_SMALL
2139
                            );
2140
                        } else {
2141
                            $action .= Display::return_icon('edit_na.png', get_lang('Comment'), [], ICON_SIZE_SMALL);
2142
                        }
2143
                    } else {
2144
                        if ($blockEdition && !api_is_platform_admin()) {
2145
                            $editLink = '';
2146
                    } else {
2147
                        if ($qualification_exists) {
2148
                                $editLink = '<a href="'.$url.'edit.php?'.api_get_cidreq(
2149
                                    ).'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang(
2150
                                        'Edit'
2151
                                    ).'"  >'.
2152
                                Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>';
2153
                        } else {
2154
                                $editLink = '<a href="'.$url.'edit.php?'.api_get_cidreq(
2155
                                    ).'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang(
2156
                                        'Modify'
2157
                                    ).'">'.
2158
                                Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>';
2159
                        }
2160
                        }
2161
                        $action .= $editLink;
2162
                    }
2163
2164
                    if ($work['contains_file']) {
2165
                        if ($locked) {
2166
                            $action .= Display::return_icon(
2167
                                'move_na.png',
2168
                                get_lang('Move'),
2169
                                [],
2170
                                ICON_SIZE_SMALL
2171
                            );
2172
                        } else {
2173
                            $action .= '<a href="'.$url.'work.php?'.api_get_cidreq().'&action=move&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Move').'">'.
2174
                                Display::return_icon('move.png', get_lang('Move'), [], ICON_SIZE_SMALL).'</a>';
2175
                        }
2176
                    }
2177
2178
                    if ($work['accepted'] == '1') {
2179
                        $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').'" >'.
2180
                            Display::return_icon('visible.png', get_lang('Invisible'), [], ICON_SIZE_SMALL).'</a>';
2181
                    } else {
2182
                        $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').'" >'.
2183
                            Display::return_icon('invisible.png', get_lang('Visible'), [], ICON_SIZE_SMALL).'</a> ';
2184
                    }
2185
2186
                    if ($locked) {
2187
                        $action .= Display::return_icon('delete_na.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2188
                    } else {
2189
                        $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').'" >'.
2190
                            Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2191
                    }
2192
                } elseif ($is_author && (empty($work['qualificator_id']) || $work['qualificator_id'] == 0)) {
2193
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2194
                        Display::return_icon('default.png', get_lang('View'), [], ICON_SIZE_SMALL).'</a>';
2195
2196
                    if (api_get_course_setting('student_delete_own_publication') == 1) {
2197
                        if (api_is_allowed_to_session_edit(false, true)) {
2198
                            $action .= '<a href="'.$url.'edit.php?'.api_get_cidreq().'&item_id='.$item_id.'&id='.$work['parent_id'].'" title="'.get_lang('Modify').'">'.
2199
                                Display::return_icon('edit.png', get_lang('Comment'), [], ICON_SIZE_SMALL).'</a>';
2200
                        }
2201
                        $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').'"  >'.
2202
                            Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
2203
                    }
2204
                } else {
2205
                    $action .= '<a href="'.$url.'view.php?'.api_get_cidreq().'&id='.$item_id.'" title="'.get_lang('View').'">'.
2206
                        Display::return_icon('default.png', get_lang('View'), [], ICON_SIZE_SMALL).'</a>';
2207
                }
2208
2209
                // Status.
2210
                if (empty($work['qualificator_id'])) {
2211
                    $qualificator_id = Display::label(get_lang('NotRevised'), 'warning');
2212
                } else {
2213
                    $qualificator_id = Display::label(get_lang('Revised'), 'success');
2214
                }
2215
                $work['qualificator_id'] = $qualificator_id.' '.$hasCorrection;
2216
                $work['actions'] = '<div class="work-action">'.$linkToDownload.$action.'</div>';
2217
                $work['correction'] = $correction;
2218
                $works[] = $work;
2219
            }
2220
        }
2221
2222
        return $works;
2223
    }
2224
}
2225
2226
/**
2227
 * Send reminder to users who have not given the task.
2228
 *
2229
 * @param int
2230
 *
2231
 * @return array
2232
 *
2233
 * @author cvargas [email protected] cfasanando, [email protected]
2234
 */
2235
function send_reminder_users_without_publication($task_data)
2236
{
2237
    $_course = api_get_course_info();
2238
    $task_id = $task_data['id'];
2239
    $task_title = !empty($task_data['title']) ? $task_data['title'] : basename($task_data['url']);
2240
    $subject = '['.api_get_setting('siteName').'] ';
2241
2242
    // The body can be as long as you wish, and any combination of text and variables
2243
    $content = get_lang('ReminderToSubmitPendingTask')."\n".get_lang('CourseName').' : '.$_course['name']."\n";
2244
    $content .= get_lang('WorkName').' : '.$task_title."\n";
2245
    $list_users = get_list_users_without_publication($task_id);
2246
    $mails_sent_to = [];
2247
    foreach ($list_users as $user) {
2248
        $name_user = api_get_person_name($user[1], $user[0], null, PERSON_NAME_EMAIL_ADDRESS);
2249
        $dear_line = get_lang('Dear')." ".api_get_person_name($user[1], $user[0]).", \n\n";
2250
        $body = $dear_line.$content;
2251
        MessageManager::send_message($user[3], $subject, $body);
2252
        $mails_sent_to[] = $name_user;
2253
    }
2254
2255
    return $mails_sent_to;
2256
}
2257
2258
/**
2259
 * @param int $workId    The work ID
2260
 * @param int $courseId  The course ID
2261
 * @param int $sessionId Optional. The session ID
2262
 */
2263
function sendEmailToDrhOnHomeworkCreation($workId, $courseId, $sessionId = 0)
2264
{
2265
    $courseInfo = api_get_course_info_by_id($courseId);
2266
    $assignment = get_work_assignment_by_id($workId, $courseId);
2267
    $work = get_work_data_by_id($workId, $courseId, $sessionId);
2268
    $workInfo = array_merge($assignment, $work);
2269
2270
    if (empty($sessionId)) {
2271
        $students = CourseManager::get_student_list_from_course_code($courseInfo['code']);
2272
    } else {
2273
        $students = CourseManager::get_student_list_from_course_code($courseInfo['code'], true, $sessionId);
2274
    }
2275
2276
    $bodyView = new Template(null, false, false, false, false, false);
2277
2278
    foreach ($students as $student) {
2279
        $studentInfo = api_get_user_info($student['user_id']);
2280
        if (empty($studentInfo)) {
2281
            continue;
2282
        }
2283
2284
        $hrms = UserManager::getDrhListFromUser($student['id']);
2285
        foreach ($hrms as $hrm) {
2286
            $hrmName = api_get_person_name($hrm['firstname'], $hrm['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
2287
2288
            $bodyView->assign('hrm_name', $hrmName);
2289
            $bodyView->assign('student', $studentInfo);
2290
            $bodyView->assign('course', $courseInfo);
2291
            $bodyView->assign('course_link', api_get_course_url($courseInfo['code'], $sessionId));
2292
            $bodyView->assign('work', $workInfo);
2293
2294
            $bodyTemplate = $bodyView->get_template('mail/new_work_alert_hrm.tpl');
2295
2296
            MessageManager::send_message(
2297
                $hrm['id'],
2298
                sprintf(
2299
                    get_lang('StudentXHasBeenAssignedNewWorkInCourseY'),
2300
                    $student['firstname'],
2301
                    $courseInfo['title']
2302
                ),
2303
                $bodyView->fetch($bodyTemplate)
2304
            );
2305
        }
2306
    }
2307
}
2308
2309
/**
2310
 * Sends an email to the students of a course when a homework is created.
2311
 *
2312
 * @param int $workId
2313
 * @param int $courseId
2314
 * @param int $sessionId
2315
 *
2316
 * @author Guillaume Viguier <[email protected]>
2317
 * @author Julio Montoya <[email protected]> Adding session support - 2011
2318
 */
2319
function sendEmailToStudentsOnHomeworkCreation($workId, $courseId, $sessionId = 0)
2320
{
2321
    $courseInfo = api_get_course_info_by_id($courseId);
2322
    $courseCode = $courseInfo['code'];
2323
    // Get the students of the course
2324
    if (empty($sessionId)) {
2325
        $students = CourseManager::get_student_list_from_course_code($courseCode);
2326
    } else {
2327
        $students = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionId);
2328
    }
2329
    $emailsubject = '['.api_get_setting('siteName').'] '.get_lang('HomeworkCreated');
2330
    $currentUser = api_get_user_info(api_get_user_id());
2331
    if (!empty($students)) {
2332
        foreach ($students as $student) {
2333
            $user_info = api_get_user_info($student['user_id']);
2334
            if (!empty($user_info)) {
2335
                $link = api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq().'&id='.$workId;
2336
                $emailbody = get_lang('Dear')." ".$user_info['complete_name'].",\n\n";
2337
                $emailbody .= get_lang('HomeworkHasBeenCreatedForTheCourse')." ".$courseCode.". "."\n\n".
2338
                    '<a href="'.$link.'">'.get_lang('PleaseCheckHomeworkPage').'</a>';
2339
                $emailbody .= "\n\n".$currentUser['complete_name'];
2340
2341
                $additionalParameters = [
2342
                    'smsType' => SmsPlugin::ASSIGNMENT_BEEN_CREATED_COURSE,
2343
                    'userId' => $student['user_id'],
2344
                    'courseTitle' => $courseCode,
2345
                    'link' => $link,
2346
                ];
2347
2348
                MessageManager::send_message_simple(
2349
                    $student['user_id'],
2350
                    $emailsubject,
2351
                    $emailbody,
2352
                    null,
2353
                    false,
2354
                    false,
2355
                    $additionalParameters,
2356
                    false
2357
                );
2358
            }
2359
        }
2360
    }
2361
}
2362
2363
/**
2364
 * @param string $url
2365
 *
2366
 * @return bool
2367
 */
2368
function is_work_exist_by_url($url)
2369
{
2370
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2371
    $url = Database::escape_string($url);
2372
    $sql = "SELECT id FROM $table WHERE url='$url'";
2373
    $result = Database::query($sql);
2374
    if (Database::num_rows($result) > 0) {
2375
        $row = Database::fetch_row($result);
2376
        if (empty($row)) {
2377
            return false;
2378
        } else {
2379
            return true;
2380
        }
2381
    } else {
2382
        return false;
2383
    }
2384
}
2385
2386
/**
2387
 * Check if a user is the author of a work document.
2388
 *
2389
 * @param int $itemId
2390
 * @param int $userId
2391
 * @param int $courseId
2392
 * @param int $sessionId
2393
 *
2394
 * @return bool
2395
 */
2396
function user_is_author($itemId, $userId = null, $courseId = 0, $sessionId = 0)
2397
{
2398
    if (empty($itemId)) {
2399
        return false;
2400
    }
2401
2402
    if (empty($userId)) {
2403
        $userId = api_get_user_id();
2404
    }
2405
2406
    $isAuthor = false;
2407
    $is_allowed_to_edit = api_is_allowed_to_edit();
2408
2409
    if ($is_allowed_to_edit) {
2410
        $isAuthor = true;
2411
    } else {
2412
        if (empty($courseId)) {
2413
            $courseId = api_get_course_int_id();
2414
        }
2415
        if (empty($sessionId)) {
2416
            $sessionId = api_get_session_id();
2417
        }
2418
2419
        $data = api_get_item_property_info($courseId, 'work', $itemId, $sessionId);
2420
        if ($data['insert_user_id'] == $userId) {
2421
            $isAuthor = true;
2422
        }
2423
2424
        $workData = get_work_data_by_id($itemId);
2425
        if ($workData['user_id'] == $userId) {
2426
            $isAuthor = true;
2427
        }
2428
    }
2429
2430
    if (!$isAuthor) {
2431
        return false;
2432
    }
2433
2434
    return $isAuthor;
2435
}
2436
2437
/**
2438
 * Get list of users who have not given the task.
2439
 *
2440
 * @param int
2441
 * @param int
2442
 *
2443
 * @return array
2444
 *
2445
 * @author cvargas
2446
 * @author Julio Montoya <[email protected]> Fixing query
2447
 */
2448
function get_list_users_without_publication($task_id, $studentId = 0)
2449
{
2450
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2451
    $table_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
2452
    $table_user = Database::get_main_table(TABLE_MAIN_USER);
2453
    $session_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2454
2455
    $users = getAllUserToWork($task_id, api_get_course_int_id());
2456
    $users = array_column($users, 'user_id');
2457
2458
    // Condition for the session
2459
    $session_id = api_get_session_id();
2460
    $course_id = api_get_course_int_id();
2461
    $task_id = intval($task_id);
2462
    $sessionCondition = api_get_session_condition($session_id);
2463
2464
    if ($session_id == 0) {
2465
        $sql = "SELECT user_id as id FROM $work_table
2466
                WHERE
2467
                    c_id = $course_id AND
2468
                    parent_id = '$task_id' AND
2469
                    active IN (0, 1)";
2470
    } else {
2471
        $sql = "SELECT user_id as id FROM $work_table
2472
                WHERE
2473
                    c_id = $course_id AND
2474
                    parent_id = '$task_id' $sessionCondition AND
2475
                    active IN (0, 1)";
2476
    }
2477
2478
    $result = Database::query($sql);
2479
    $users_with_tasks = [];
2480
    while ($row = Database::fetch_array($result)) {
2481
        $users_with_tasks[] = $row['id'];
2482
    }
2483
2484
    if ($session_id == 0) {
2485
        $sql_users = "SELECT cu.user_id, u.lastname, u.firstname, u.email
2486
                      FROM $table_course_user AS cu, $table_user AS u
2487
                      WHERE u.status != 1 and cu.c_id='".$course_id."' AND u.user_id = cu.user_id";
2488
    } else {
2489
        $sql_users = "SELECT cu.user_id, u.lastname, u.firstname, u.email
2490
                      FROM $session_course_rel_user AS cu, $table_user AS u
2491
                      WHERE
2492
                        u.status != 1 AND
2493
                        cu.c_id='".$course_id."' AND
2494
                        u.user_id = cu.user_id AND
2495
                        cu.session_id = '".$session_id."'";
2496
    }
2497
2498
    if (!empty($studentId)) {
2499
        $sql_users .= " AND u.user_id = ".intval($studentId);
2500
    }
2501
2502
    $group_id = api_get_group_id();
2503
    $new_group_user_list = [];
2504
2505
    if ($group_id) {
2506
        $groupInfo = GroupManager::get_group_properties($group_id);
2507
        $group_user_list = GroupManager::get_subscribed_users($groupInfo);
2508
        if (!empty($group_user_list)) {
2509
            foreach ($group_user_list as $group_user) {
2510
                $new_group_user_list[] = $group_user['user_id'];
2511
            }
2512
        }
2513
    }
2514
2515
    $result_users = Database::query($sql_users);
2516
    $users_without_tasks = [];
2517
    while ($rowUsers = Database::fetch_array($result_users)) {
2518
        $userId = $rowUsers['user_id'];
2519
        if (in_array($userId, $users_with_tasks)) {
2520
            continue;
2521
        }
2522
2523
        if ($group_id && !in_array($userId, $new_group_user_list)) {
2524
            continue;
2525
        }
2526
2527
        if (!empty($users)) {
2528
            if (!in_array($userId, $users)) {
2529
                continue;
2530
            }
2531
        }
2532
2533
        $row_users = [];
2534
        $row_users[0] = $rowUsers['lastname'];
2535
        $row_users[1] = $rowUsers['firstname'];
2536
        $row_users[2] = Display::encrypted_mailto_link($rowUsers['email']);
2537
        $row_users[3] = $userId;
2538
        $users_without_tasks[] = $row_users;
2539
    }
2540
2541
    return $users_without_tasks;
2542
}
2543
2544
/**
2545
 * Display list of users who have not given the task.
2546
 *
2547
 * @param int task id
2548
 * @param int $studentId
2549
 *
2550
 * @author cvargas [email protected] cfasanando, [email protected]
2551
 * @author Julio Montoya <[email protected]> Fixes
2552
 */
2553
function display_list_users_without_publication($task_id, $studentId = null)
2554
{
2555
    $origin = api_get_origin();
2556
    $table_header[] = [get_lang('LastName'), true];
2557
    $table_header[] = [get_lang('FirstName'), true];
2558
    $table_header[] = [get_lang('Email'), true];
2559
2560
    $data = get_list_users_without_publication($task_id);
2561
2562
    $sorting_options = [];
2563
    $sorting_options['column'] = 1;
2564
    $paging_options = [];
2565
    $my_params = [];
2566
2567
    if (isset($_GET['edit_dir'])) {
2568
        $my_params['edit_dir'] = Security::remove_XSS($_GET['edit_dir']);
2569
    }
2570
    if (isset($_GET['list'])) {
2571
        $my_params['list'] = Security::remove_XSS($_GET['list']);
2572
    }
2573
    $my_params['origin'] = $origin;
2574
    $my_params['id'] = intval($_GET['id']);
2575
2576
    //$column_show
2577
    $column_show[] = 1;
2578
    $column_show[] = 1;
2579
    $column_show[] = 1;
2580
    Display::display_sortable_config_table(
2581
        'work',
2582
        $table_header,
2583
        $data,
2584
        $sorting_options,
2585
        $paging_options,
2586
        $my_params,
2587
        $column_show
2588
    );
2589
}
2590
2591
/**
2592
 * @param int $documentId
2593
 * @param int $workId
2594
 * @param int $courseId
2595
 */
2596
function addDocumentToWork($documentId, $workId, $courseId)
2597
{
2598
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2599
    $params = [
2600
        'document_id' => $documentId,
2601
        'work_id' => $workId,
2602
        'c_id' => $courseId,
2603
    ];
2604
    Database::insert($table, $params);
2605
}
2606
2607
/**
2608
 * @param int $documentId
2609
 * @param int $workId
2610
 * @param int $courseId
2611
 *
2612
 * @return array
2613
 */
2614
function getDocumentToWork($documentId, $workId, $courseId)
2615
{
2616
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2617
    $params = [
2618
        'document_id = ? and work_id = ? and c_id = ?' => [$documentId, $workId, $courseId],
2619
    ];
2620
2621
    return Database::select('*', $table, ['where' => $params]);
2622
}
2623
2624
/**
2625
 * @param int $documentId
2626
 * @param int $workId
2627
 * @param int $courseId
2628
 * @param int $sessionId
2629
 * @param int $userId
2630
 * @param int $active
2631
 *
2632
 * @return array
2633
 */
2634
function getDocumentToWorkPerUser($documentId, $workId, $courseId, $sessionId, $userId, $active = 1)
2635
{
2636
    $workRel = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2637
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
2638
2639
    $documentId = intval($documentId);
2640
    $workId = intval($workId);
2641
    $courseId = intval($courseId);
2642
    $userId = intval($userId);
2643
    $sessionId = intval($sessionId);
2644
    $active = intval($active);
2645
    $sessionCondition = api_get_session_condition($sessionId);
2646
2647
    $sql = "SELECT w.* FROM $work w 
2648
            INNER JOIN $workRel rel 
2649
            ON (w.parent_id = rel.work_id)
2650
            WHERE
2651
                w.document_id = $documentId AND
2652
                w.parent_id = $workId AND
2653
                w.c_id = $courseId
2654
                $sessionCondition AND
2655
                user_id = $userId AND
2656
                active = $active
2657
            ";
2658
2659
    $result = Database::query($sql);
2660
    $workInfo = [];
2661
    if (Database::num_rows($result)) {
2662
        $workInfo = Database::fetch_array($result, 'ASSOC');
2663
    }
2664
2665
    return $workInfo;
2666
}
2667
2668
/**
2669
 * @param int $workId
2670
 * @param int $courseId
2671
 *
2672
 * @return array
2673
 */
2674
function getAllDocumentToWork($workId, $courseId)
2675
{
2676
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2677
    $params = [
2678
        'work_id = ? and c_id = ?' => [$workId, $courseId],
2679
    ];
2680
2681
    return Database::select('*', $table, ['where' => $params]);
2682
}
2683
2684
/**
2685
 * @param int $documentId
2686
 * @param int $workId
2687
 * @param int $courseId
2688
 */
2689
function deleteDocumentToWork($documentId, $workId, $courseId)
2690
{
2691
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_DOCUMENT);
2692
    $params = [
2693
        'document_id = ? and work_id = ? and c_id = ?' => [$documentId, $workId, $courseId],
2694
    ];
2695
    Database::delete($table, $params);
2696
}
2697
2698
/**
2699
 * @param int $userId
2700
 * @param int $workId
2701
 * @param int $courseId
2702
 */
2703
function addUserToWork($userId, $workId, $courseId)
2704
{
2705
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2706
    $params = [
2707
        'user_id' => $userId,
2708
        'work_id' => $workId,
2709
        'c_id' => $courseId,
2710
    ];
2711
    Database::insert($table, $params);
2712
}
2713
2714
/**
2715
 * @param int $userId
2716
 * @param int $workId
2717
 * @param int $courseId
2718
 *
2719
 * @return array
2720
 */
2721
function getUserToWork($userId, $workId, $courseId)
2722
{
2723
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2724
    $params = [
2725
        'user_id = ? and work_id = ? and c_id = ?' => [$userId, $workId, $courseId],
2726
    ];
2727
2728
    return Database::select('*', $table, ['where' => $params]);
2729
}
2730
2731
/**
2732
 * @param int  $workId
2733
 * @param int  $courseId
2734
 * @param bool $getCount
2735
 *
2736
 * @return array|int
2737
 */
2738
function getAllUserToWork($workId, $courseId, $getCount = false)
2739
{
2740
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2741
    $params = [
2742
        'work_id = ? and c_id = ?' => [$workId, $courseId],
2743
    ];
2744
    if ($getCount) {
2745
        $count = 0;
2746
        $result = Database::select(
2747
            'count(user_id) as count',
2748
            $table,
2749
            ['where' => $params],
2750
            'simple'
2751
        );
2752
        if (!empty($result)) {
2753
            $count = intval($result['count']);
2754
        }
2755
2756
        return $count;
2757
    } else {
2758
        return Database::select('*', $table, ['where' => $params]);
2759
    }
2760
}
2761
2762
/**
2763
 * @param int $userId
2764
 * @param int $workId
2765
 * @param int $courseId
2766
 */
2767
function deleteUserToWork($userId, $workId, $courseId)
2768
{
2769
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_REL_USER);
2770
    $params = [
2771
        'user_id = ? and work_id = ? and c_id = ?' => [$userId, $workId, $courseId],
2772
    ];
2773
    Database::delete($table, $params);
2774
}
2775
2776
/**
2777
 * @param int $userId
2778
 * @param int $workId
2779
 * @param int $courseId
2780
 *
2781
 * @return bool
2782
 */
2783
function userIsSubscribedToWork($userId, $workId, $courseId)
2784
{
2785
    $subscribedUsers = getAllUserToWork($workId, $courseId);
2786
2787
    if (empty($subscribedUsers)) {
2788
        return true;
2789
    } else {
2790
        $subscribedUsersList = [];
2791
        foreach ($subscribedUsers as $item) {
2792
            $subscribedUsersList[] = $item['user_id'];
2793
        }
2794
        if (in_array($userId, $subscribedUsersList)) {
2795
            return true;
2796
        }
2797
    }
2798
2799
    return false;
2800
}
2801
2802
/**
2803
 * Get the list of students that have to submit their work.
2804
 *
2805
 * @param int  $workId    The internal ID of the assignment
2806
 * @param int  $courseId  The course ID
2807
 * @param int  $groupId   The group ID, if any
2808
 * @param int  $sessionId The session ID, if any
2809
 * @param bool $getCount  Whether we want just the amount or the full result
2810
 *
2811
 * @return array|int An integer (if we just asked for the count) or an array of users
2812
 */
2813
function getStudentSubscribedToWork(
2814
    $workId,
2815
    $courseId,
2816
    $groupId = null,
2817
    $sessionId = null,
2818
    $getCount = false
2819
) {
2820
    $usersInWork = null;
2821
    $usersInCourse = null;
2822
2823
    if (empty($groupId)) {
2824
        $courseInfo = api_get_course_info_by_id($courseId);
2825
        $status = STUDENT;
2826
        if (!empty($sessionId)) {
2827
            $status = 0;
2828
        }
2829
        $usersInCourse = CourseManager::get_user_list_from_course_code(
2830
            $courseInfo['code'],
2831
            $sessionId,
2832
            null,
2833
            null,
2834
            $status,
2835
            $getCount
2836
        );
2837
    } else {
2838
        $usersInCourse = GroupManager::get_users(
2839
            $groupId,
2840
            false,
2841
            null,
2842
            null,
2843
            $getCount,
2844
            $courseId
2845
        );
2846
    }
2847
2848
    $usersInWork = getAllUserToWork($workId, $courseId, $getCount);
2849
2850
    if (empty($usersInWork)) {
2851
        return $usersInCourse;
2852
    } else {
2853
        return $usersInWork;
2854
    }
2855
}
2856
2857
/**
2858
 * @param int  $userId
2859
 * @param int  $workId
2860
 * @param int  $courseId
2861
 * @param bool $forceAccessForCourseAdmins
2862
 *
2863
 * @return bool
2864
 */
2865
function allowOnlySubscribedUser($userId, $workId, $courseId, $forceAccessForCourseAdmins = false)
2866
{
2867
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
2868
        return true;
2869
    }
2870
2871
    if ($forceAccessForCourseAdmins) {
2872
        if (api_is_course_admin() || api_is_coach()) {
2873
            return true;
2874
        }
2875
    }
2876
2877
    return userIsSubscribedToWork($userId, $workId, $courseId);
2878
}
2879
2880
/**
2881
 * @param int   $workId
2882
 * @param array $courseInfo
2883
 * @param int   $documentId
2884
 *
2885
 * @return array
2886
 */
2887
function getDocumentTemplateFromWork($workId, $courseInfo, $documentId)
2888
{
2889
    $documents = getAllDocumentToWork($workId, $courseInfo['real_id']);
2890
    if (!empty($documents)) {
2891
        foreach ($documents as $doc) {
2892
            if ($documentId != $doc['document_id']) {
2893
                continue;
2894
            }
2895
            $docData = DocumentManager::get_document_data_by_id($doc['document_id'], $courseInfo['code']);
2896
            $fileInfo = pathinfo($docData['path']);
2897
            if ($fileInfo['extension'] == 'html') {
2898
                if (file_exists($docData['absolute_path']) && is_file($docData['absolute_path'])) {
2899
                    $docData['file_content'] = file_get_contents($docData['absolute_path']);
2900
2901
                    return $docData;
2902
                }
2903
            }
2904
        }
2905
    }
2906
2907
    return [];
2908
}
2909
2910
/**
2911
 * @param int   $workId
2912
 * @param array $courseInfo
2913
 *
2914
 * @return string
2915
 */
2916
function getAllDocumentsFromWorkToString($workId, $courseInfo)
2917
{
2918
    $documents = getAllDocumentToWork($workId, $courseInfo['real_id']);
2919
    $content = null;
2920
    if (!empty($documents)) {
2921
        $content .= '<ul class="nav nav-list well">';
2922
        $content .= '<li class="nav-header">'.get_lang('Documents').'</li>';
2923
        foreach ($documents as $doc) {
2924
            $docData = DocumentManager::get_document_data_by_id($doc['document_id'], $courseInfo['code']);
2925
            if ($docData) {
2926
                $content .= '<li><a target="_blank" href="'.$docData['url'].'">'.$docData['title'].'</a></li>';
2927
            }
2928
        }
2929
        $content .= '</ul><br />';
2930
    }
2931
2932
    return $content;
2933
}
2934
2935
/**
2936
 * Returns fck editor toolbar.
2937
 *
2938
 * @return array
2939
 */
2940
function getWorkDescriptionToolbar()
2941
{
2942
    return [
2943
        'ToolbarStartExpanded' => 'true',
2944
        'ToolbarSet' => 'Work',
2945
        'Width' => '100%',
2946
        'Height' => '400',
2947
    ];
2948
}
2949
2950
/**
2951
 * @param array $work
2952
 *
2953
 * @return array
2954
 */
2955
function getWorkComments($work)
2956
{
2957
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
2958
    $userTable = Database::get_main_table(TABLE_MAIN_USER);
2959
2960
    $courseId = intval($work['c_id']);
2961
    $workId = intval($work['id']);
2962
2963
    if (empty($courseId) || empty($workId)) {
2964
        return [];
2965
    }
2966
2967
    $sql = "SELECT
2968
                c.id,
2969
                c.user_id
2970
            FROM $commentTable c
2971
            INNER JOIN $userTable u
2972
            ON (u.id = c.user_id)
2973
            WHERE c_id = $courseId AND work_id = $workId
2974
            ORDER BY sent_at
2975
            ";
2976
    $result = Database::query($sql);
2977
    $comments = Database::store_result($result, 'ASSOC');
2978
    if (!empty($comments)) {
2979
        foreach ($comments as &$comment) {
2980
            $userInfo = api_get_user_info($comment['user_id']);
2981
            $comment['picture'] = $userInfo['avatar'];
2982
            $comment['complete_name'] = $userInfo['complete_name_with_username'];
2983
            $commentInfo = getWorkComment($comment['id']);
2984
            if (!empty($commentInfo)) {
2985
                $comment = array_merge($comment, $commentInfo);
2986
            }
2987
        }
2988
    }
2989
2990
    return $comments;
2991
}
2992
2993
/**
2994
 * Get total score from a work list.
2995
 *
2996
 * @param $workList
2997
 *
2998
 * @return int|null
2999
 */
3000
function getTotalWorkScore($workList)
3001
{
3002
    $count = 0;
3003
    foreach ($workList as $data) {
3004
        $count += $data['qualification_score'];
3005
    }
3006
3007
    return $count;
3008
}
3009
3010
/**
3011
 * Get comment count from a work list (docs sent by students).
3012
 *
3013
 * @param array $workList
3014
 * @param array $courseInfo
3015
 *
3016
 * @return int|null
3017
 */
3018
function getTotalWorkComment($workList, $courseInfo = [])
3019
{
3020
    if (empty($courseInfo)) {
3021
        $courseInfo = api_get_course_info();
3022
    }
3023
3024
    $count = 0;
3025
    foreach ($workList as $data) {
3026
        $count += getWorkCommentCount($data['id'], $courseInfo);
3027
    }
3028
3029
    return $count;
3030
}
3031
3032
/**
3033
 * Get comment count for a specific work sent by a student.
3034
 *
3035
 * @param int   $id
3036
 * @param array $courseInfo
3037
 *
3038
 * @return int
3039
 */
3040
function getWorkCommentCount($id, $courseInfo = [])
3041
{
3042
    if (empty($courseInfo)) {
3043
        $courseInfo = api_get_course_info();
3044
    }
3045
3046
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3047
    $id = intval($id);
3048
3049
    $sql = "SELECT count(*) as count
3050
            FROM $commentTable
3051
            WHERE work_id = $id AND c_id = ".$courseInfo['real_id'];
3052
3053
    $result = Database::query($sql);
3054
    if (Database::num_rows($result)) {
3055
        $comment = Database::fetch_array($result);
3056
3057
        return $comment['count'];
3058
    }
3059
3060
    return 0;
3061
}
3062
3063
/**
3064
 * Get comment count for a specific parent.
3065
 *
3066
 * @param int   $parentId
3067
 * @param array $courseInfo
3068
 * @param int   $sessionId
3069
 *
3070
 * @return int
3071
 */
3072
function getWorkCommentCountFromParent(
3073
    $parentId,
3074
    $courseInfo = [],
3075
    $sessionId = 0
3076
) {
3077
    if (empty($courseInfo)) {
3078
        $courseInfo = api_get_course_info();
3079
    }
3080
3081
    if (empty($sessionId)) {
3082
        $sessionId = api_get_session_id();
3083
    } else {
3084
        $sessionId = intval($sessionId);
3085
    }
3086
3087
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3088
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3089
    $parentId = intval($parentId);
3090
    $sessionCondition = api_get_session_condition($sessionId, false, false, 'w.session_id');
3091
3092
    $sql = "SELECT count(*) as count
3093
            FROM $commentTable c INNER JOIN $work w
3094
            ON c.c_id = w.c_id AND w.id = c.work_id
3095
            WHERE
3096
                $sessionCondition AND
3097
                parent_id = $parentId AND
3098
                w.c_id = ".$courseInfo['real_id'];
3099
3100
    $result = Database::query($sql);
3101
    if (Database::num_rows($result)) {
3102
        $comment = Database::fetch_array($result);
3103
3104
        return $comment['count'];
3105
    }
3106
3107
    return 0;
3108
}
3109
3110
/**
3111
 * Get last work information from parent.
3112
 *
3113
 * @param int   $parentId
3114
 * @param array $courseInfo
3115
 * @param int   $sessionId
3116
 *
3117
 * @return int
3118
 */
3119
function getLastWorkStudentFromParent(
3120
    $parentId,
3121
    $courseInfo = [],
3122
    $sessionId = 0
3123
) {
3124
    if (empty($courseInfo)) {
3125
        $courseInfo = api_get_course_info();
3126
    }
3127
3128
    if (empty($sessionId)) {
3129
        $sessionId = api_get_session_id();
3130
    } else {
3131
        $sessionId = intval($sessionId);
3132
    }
3133
3134
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3135
    $sessionCondition = api_get_session_condition($sessionId, false);
3136
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3137
    $parentId = intval($parentId);
3138
3139
    $sql = "SELECT w.*
3140
            FROM $commentTable c INNER JOIN $work w
3141
            ON c.c_id = w.c_id AND w.id = c.work_id
3142
            WHERE
3143
                $sessionCondition AND
3144
                parent_id = $parentId AND
3145
                w.c_id = ".$courseInfo['real_id']."
3146
            ORDER BY w.sent_date
3147
            LIMIT 1
3148
            ";
3149
3150
    $result = Database::query($sql);
3151
    if (Database::num_rows($result)) {
3152
        $comment = Database::fetch_array($result, 'ASSOC');
3153
3154
        return $comment;
3155
    }
3156
3157
    return [];
3158
}
3159
3160
/**
3161
 * Get last work information from parent.
3162
 *
3163
 * @param int   $userId
3164
 * @param array $parentInfo
3165
 * @param array $courseInfo
3166
 * @param int   $sessionId
3167
 *
3168
 * @return int
3169
 */
3170
function getLastWorkStudentFromParentByUser(
3171
    $userId,
3172
    $parentInfo,
3173
    $courseInfo = [],
3174
    $sessionId = 0
3175
) {
3176
    if (empty($courseInfo)) {
3177
        $courseInfo = api_get_course_info();
3178
    }
3179
3180
    if (empty($sessionId)) {
3181
        $sessionId = api_get_session_id();
3182
    } else {
3183
        $sessionId = intval($sessionId);
3184
    }
3185
3186
    $userId = intval($userId);
3187
    $work = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3188
    if (empty($parentInfo)) {
3189
        return false;
3190
    }
3191
    $parentId = $parentInfo['id'];
3192
3193
    $sessionCondition = api_get_session_condition($sessionId);
3194
3195
    $sql = "SELECT *
3196
            FROM $work
3197
            WHERE
3198
                user_id = $userId
3199
                $sessionCondition AND
3200
                parent_id = $parentId AND
3201
                c_id = ".$courseInfo['real_id']."
3202
            ORDER BY sent_date DESC
3203
            LIMIT 1
3204
            ";
3205
    $result = Database::query($sql);
3206
    if (Database::num_rows($result)) {
3207
        $work = Database::fetch_array($result, 'ASSOC');
3208
        $work['qualification_rounded'] = formatWorkScore($work['qualification'], $parentInfo['qualification']);
3209
3210
        return $work;
3211
    }
3212
3213
    return [];
3214
}
3215
3216
/**
3217
 * @param float $score
3218
 * @param int   $weight
3219
 *
3220
 * @return string
3221
 */
3222
function formatWorkScore($score, $weight)
3223
{
3224
    $label = 'info';
3225
    $weight = (int) $weight;
3226
    $relativeScore = 0;
3227
    if (!empty($weight)) {
3228
        $relativeScore = $score / $weight;
3229
    }
3230
3231
    if ($relativeScore < 0.5) {
3232
        $label = 'important';
3233
    } elseif ($relativeScore < 0.75) {
3234
        $label = 'warning';
3235
    }
3236
3237
    $scoreBasedInModel = ExerciseLib::convertScoreToModel($relativeScore * 100);
3238
    if (empty($scoreBasedInModel)) {
3239
        $finalScore = api_number_format($score, 1).' / '.$weight;
3240
3241
        return Display::label(
3242
            $finalScore,
3243
            $label
3244
        );
3245
    } else {
3246
        $finalScore = $scoreBasedInModel;
3247
3248
        return $finalScore;
3249
    }
3250
}
3251
3252
/**
3253
 * @param int   $id         comment id
3254
 * @param array $courseInfo
3255
 *
3256
 * @return string
3257
 */
3258
function getWorkComment($id, $courseInfo = [])
3259
{
3260
    if (empty($courseInfo)) {
3261
        $courseInfo = api_get_course_info();
3262
    }
3263
3264
    if (empty($courseInfo['real_id'])) {
3265
        return [];
3266
    }
3267
3268
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3269
    $id = intval($id);
3270
3271
    $sql = "SELECT * FROM $commentTable
3272
            WHERE id = $id AND c_id = ".$courseInfo['real_id'];
3273
    $result = Database::query($sql);
3274
    $comment = [];
3275
    if (Database::num_rows($result)) {
3276
        $comment = Database::fetch_array($result, 'ASSOC');
3277
        $filePath = null;
3278
        $fileUrl = null;
3279
        $deleteUrl = null;
3280
        $fileName = null;
3281
        if (!empty($comment['file'])) {
3282
            $work = get_work_data_by_id($comment['work_id']);
3283
            $workParent = get_work_data_by_id($work['parent_id']);
3284
            $filePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/'.$workParent['url'].'/'.$comment['file'];
3285
            $fileUrl = api_get_path(WEB_CODE_PATH).'work/download_comment_file.php?comment_id='.$id.'&'.api_get_cidreq();
3286
            $deleteUrl = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$comment['work_id'].'&action=delete_attachment&comment_id='.$id;
3287
            $fileParts = explode('_', $comment['file']);
3288
            $fileName = str_replace($fileParts[0].'_'.$fileParts[1].'_', '', $comment['file']);
3289
        }
3290
        $comment['delete_file_url'] = $deleteUrl;
3291
        $comment['file_path'] = $filePath;
3292
        $comment['file_url'] = $fileUrl;
3293
        $comment['file_name_to_show'] = $fileName;
3294
        $comment['sent_at_with_label'] = Display::dateToStringAgoAndLongDate($comment['sent_at']);
3295
    }
3296
3297
    return $comment;
3298
}
3299
3300
/**
3301
 * @param int   $id
3302
 * @param array $courseInfo
3303
 */
3304
function deleteCommentFile($id, $courseInfo = [])
3305
{
3306
    $workComment = getWorkComment($id, $courseInfo);
3307
    if (isset($workComment['file']) && !empty($workComment['file'])) {
3308
        if (file_exists($workComment['file_path'])) {
3309
            $result = my_delete($workComment['file_path']);
3310
            if ($result) {
3311
                $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3312
                $params = ['file' => ''];
3313
                Database::update(
3314
                    $commentTable,
3315
                    $params,
3316
                    ['id = ? AND c_id = ? ' => [$workComment['id'], $workComment['c_id']]]
3317
                );
3318
            }
3319
        }
3320
    }
3321
}
3322
3323
/**
3324
 * Adds a comments to the work document.
3325
 *
3326
 * @param array $courseInfo
3327
 * @param int   $userId
3328
 * @param array $parentWork
3329
 * @param array $work
3330
 * @param array $data
3331
 *
3332
 * @return int
3333
 */
3334
function addWorkComment($courseInfo, $userId, $parentWork, $work, $data)
3335
{
3336
    $fileData = isset($data['attachment']) ? $data['attachment'] : null;
3337
    $commentTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT);
3338
3339
    // If no attachment and no comment then don't save comment
3340
    if (empty($fileData['name']) && empty($data['comment'])) {
3341
        return false;
3342
    }
3343
3344
    $params = [
3345
        'work_id' => $work['id'],
3346
        'c_id' => $work['c_id'],
3347
        'user_id' => $userId,
3348
        'comment' => $data['comment'],
3349
        'sent_at' => api_get_utc_datetime(),
3350
    ];
3351
3352
    $commentId = Database::insert($commentTable, $params);
3353
3354
    if ($commentId) {
3355
        Display::addFlash(
3356
            Display::return_message(get_lang('CommentAdded'))
3357
        );
3358
3359
        $sql = "UPDATE $commentTable SET id = iid WHERE iid = $commentId";
3360
        Database::query($sql);
3361
    }
3362
3363
    $userIdListToSend = [];
3364
    if (api_is_allowed_to_edit()) {
3365
        if (isset($data['send_email']) && $data['send_email']) {
3366
            // Teacher sends a feedback
3367
            $userIdListToSend = [$work['user_id']];
3368
        }
3369
    } else {
3370
        $sessionId = api_get_session_id();
3371
        if (empty($sessionId)) {
3372
            $teachers = CourseManager::get_teacher_list_from_course_code(
3373
                $courseInfo['code']
3374
            );
3375
            if (!empty($teachers)) {
3376
                $userIdListToSend = array_keys($teachers);
3377
            }
3378
        } else {
3379
            $teachers = SessionManager::getCoachesByCourseSession(
3380
                $sessionId,
3381
                $courseInfo['real_id']
3382
            );
3383
3384
            if (!empty($teachers)) {
3385
                $userIdListToSend = array_values($teachers);
3386
            }
3387
        }
3388
3389
        $sendNotification = api_get_course_setting('email_to_teachers_on_new_work_feedback', api_get_course_id());
3390
        if ($sendNotification != 1) {
3391
            $userIdListToSend = [];
3392
        }
3393
    }
3394
3395
    $url = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$work['id'];
3396
    $subject = sprintf(get_lang('ThereIsANewWorkFeedback'), $parentWork['title']);
3397
    $content = sprintf(get_lang('ThereIsANewWorkFeedbackInWorkXHere'), $work['title'], $url);
3398
3399
    if (!empty($data['comment'])) {
3400
        $content .= '<br /><b>'.get_lang('Comment').':</b><br />'.$data['comment'];
3401
    }
3402
3403
    if (!empty($userIdListToSend)) {
3404
        foreach ($userIdListToSend as $userIdToSend) {
3405
            MessageManager::send_message_simple(
3406
                $userIdToSend,
3407
                $subject,
3408
                $content
3409
            );
3410
        }
3411
    }
3412
3413
    if (!empty($commentId) && !empty($fileData)) {
3414
        $workParent = get_work_data_by_id($work['parent_id']);
3415
        if (!empty($workParent)) {
3416
            $uploadDir = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work'.$workParent['url'];
3417
            $newFileName = 'comment_'.$commentId.'_'.php2phps(api_replace_dangerous_char($fileData['name']));
3418
            $newFilePath = $uploadDir.'/'.$newFileName;
3419
            $result = move_uploaded_file($fileData['tmp_name'], $newFilePath);
3420
            if ($result) {
3421
                $params = ['file' => $newFileName];
3422
                Database::update(
3423
                    $commentTable,
3424
                    $params,
3425
                    ['id = ? AND c_id = ? ' => [$commentId, $work['c_id']]]
3426
                );
3427
            }
3428
        }
3429
    }
3430
}
3431
3432
/**
3433
 * @param array $work
3434
 * @param array $workParent
3435
 *
3436
 * @return string
3437
 */
3438
function getWorkCommentForm($work, $workParent)
3439
{
3440
    $url = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$work['id'].'&action=send_comment&'.api_get_cidreq();
3441
    $form = new FormValidator(
3442
        'work_comment',
3443
        'post',
3444
        $url,
3445
        '',
3446
        ['enctype' => "multipart/form-data"]
3447
    );
3448
3449
    $qualification = $workParent['qualification'];
3450
3451
    if (api_is_allowed_to_edit()) {
3452
        if (!empty($qualification) && intval($qualification) > 0) {
3453
            $model = ExerciseLib::getCourseScoreModel();
3454
            if (empty($model)) {
3455
                $form->addFloat(
3456
                    'qualification',
3457
                    [get_lang('Qualification'), " / ".$qualification],
3458
                    false,
3459
                    [],
3460
                    false,
3461
                    0,
3462
                    $qualification
3463
                );
3464
            } else {
3465
                ExerciseLib::addScoreModelInput(
3466
                    $form,
3467
                    'qualification',
3468
                    $qualification,
3469
                    $work['qualification']
3470
                );
3471
            }
3472
            $form->addFile('file', get_lang('Correction'));
3473
            $form->setDefaults(['qualification' => $work['qualification']]);
3474
        }
3475
    }
3476
3477
    Skill::addSkillsToUserForm($form, ITEM_TYPE_STUDENT_PUBLICATION, $workParent['id'], $work['user_id'], $work['id']);
3478
    $form->addHtmlEditor('comment', get_lang('Comment'), false);
3479
    $form->addFile('attachment', get_lang('Attachment'));
3480
    $form->addElement('hidden', 'id', $work['id']);
3481
3482
    if (api_is_allowed_to_edit()) {
3483
        $form->addCheckBox(
3484
            'send_email',
3485
            null,
3486
            get_lang('SendMailToStudent')
3487
        );
3488
    }
3489
3490
    $form->addButtonSend(get_lang('Send'), 'button');
3491
3492
    return $form->returnForm();
3493
}
3494
3495
/**
3496
 * @param array $homework result of get_work_assignment_by_id()
3497
 *
3498
 * @return array
3499
 */
3500
function getWorkDateValidationStatus($homework)
3501
{
3502
    $message = null;
3503
    $has_expired = false;
3504
    $has_ended = false;
3505
3506
    if (!empty($homework)) {
3507
        if (!empty($homework['expires_on']) || !empty($homework['ends_on'])) {
3508
            $time_now = time();
3509
3510
            if (!empty($homework['expires_on'])) {
3511
                $time_expires = api_strtotime($homework['expires_on'], 'UTC');
3512
                $difference = $time_expires - $time_now;
3513
                if ($difference < 0) {
3514
                    $has_expired = true;
3515
                }
3516
            }
3517
3518
            if (empty($homework['expires_on'])) {
3519
                $has_expired = false;
3520
            }
3521
3522
            if (!empty($homework['ends_on'])) {
3523
                $time_ends = api_strtotime($homework['ends_on'], 'UTC');
3524
                $difference2 = $time_ends - $time_now;
3525
                if ($difference2 < 0) {
3526
                    $has_ended = true;
3527
                }
3528
            }
3529
3530
            $ends_on = api_convert_and_format_date($homework['ends_on']);
3531
            $expires_on = api_convert_and_format_date($homework['expires_on']);
3532
        }
3533
3534
        if ($has_ended) {
3535
            $message = Display::return_message(get_lang('EndDateAlreadyPassed').' '.$ends_on, 'error');
3536
        } elseif ($has_expired) {
3537
            $message = Display::return_message(get_lang('ExpiryDateAlreadyPassed').' '.$expires_on, 'warning');
3538
        } else {
3539
            if ($has_expired) {
3540
                $message = Display::return_message(get_lang('ExpiryDateToSendWorkIs').' '.$expires_on);
3541
            }
3542
        }
3543
    }
3544
3545
    return [
3546
        'message' => $message,
3547
        'has_ended' => $has_ended,
3548
        'has_expired' => $has_expired,
3549
    ];
3550
}
3551
3552
/**
3553
 * @param FormValidator $form
3554
 * @param int           $uploadFormType
3555
 */
3556
function setWorkUploadForm($form, $uploadFormType = 0)
3557
{
3558
    $form->addHeader(get_lang('UploadADocument'));
3559
    $form->addHidden('contains_file', 0, ['id' => 'contains_file_id']);
3560
    $form->addHidden('active', 1);
3561
    $form->addHidden('accepted', 1);
3562
    $form->addElement('text', 'title', get_lang('Title'), ['id' => 'file_upload']);
3563
    $form->addElement(
3564
        'text',
3565
        'extension',
3566
        get_lang('FileExtension'),
3567
        ['id' => 'file_extension', 'readonly' => 'readonly']
3568
    );
3569
    $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
3570
3571
    switch ($uploadFormType) {
3572
        case 0:
3573
            // File and text.
3574
            $form->addElement(
3575
                'file',
3576
                'file',
3577
                get_lang('UploadADocument'),
3578
                'size="40" onchange="updateDocumentTitle(this.value)"'
3579
            );
3580
            $form->addProgress();
3581
            $form->addHtmlEditor('description', get_lang('Description'), false, false, getWorkDescriptionToolbar());
3582
            break;
3583
        case 1:
3584
            // Only text.
3585
            $form->addHtmlEditor('description', get_lang('Description'), false, false, getWorkDescriptionToolbar());
3586
            $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required');
3587
            break;
3588
        case 2:
3589
            // Only file.
3590
            $form->addElement(
3591
                'file',
3592
                'file',
3593
                get_lang('UploadADocument'),
3594
                'size="40" onchange="updateDocumentTitle(this.value)"'
3595
            );
3596
            $form->addProgress();
3597
            $form->addRule('file', get_lang('ThisFieldIsRequired'), 'required');
3598
            break;
3599
    }
3600
3601
    $form->addButtonUpload(get_lang('Upload'), 'submitWork');
3602
}
3603
3604
/**
3605
 * @param array $my_folder_data
3606
 * @param array $_course
3607
 * @param bool  $isCorrection
3608
 * @param array $workInfo
3609
 * @param array $file
3610
 *
3611
 * @return array
3612
 */
3613
function uploadWork($my_folder_data, $_course, $isCorrection = false, $workInfo = [], $file = [])
3614
{
3615
    if (isset($_FILES['file']) && !empty($_FILES['file'])) {
3616
        $file = $_FILES['file'];
3617
    }
3618
3619
    if (empty($file['size'])) {
3620
        return [
3621
            'error' => Display:: return_message(
3622
                get_lang('UplUploadFailedSizeIsZero'),
3623
                'error'
3624
            ),
3625
        ];
3626
    }
3627
    $updir = api_get_path(SYS_COURSE_PATH).$_course['path'].'/work/'; //directory path to upload
3628
3629
    // Try to add an extension to the file if it has'nt one
3630
    $filename = add_ext_on_mime(stripslashes($file['name']), $file['type']);
3631
3632
    // Replace dangerous characters
3633
    $filename = api_replace_dangerous_char($filename);
3634
3635
    // Transform any .php file in .phps fo security
3636
    $filename = php2phps($filename);
3637
    $filesize = filesize($file['tmp_name']);
3638
3639
    if (empty($filesize)) {
3640
        return [
3641
            'error' => Display::return_message(
3642
                get_lang('UplUploadFailedSizeIsZero'),
3643
                'error'
3644
            ),
3645
        ];
3646
    } elseif (!filter_extension($new_file_name)) {
3647
        return [
3648
            'error' => Display::return_message(
3649
                get_lang('UplUnableToSaveFileFilteredExtension'),
3650
                'error'
3651
            ),
3652
        ];
3653
    }
3654
3655
    $totalSpace = DocumentManager::documents_total_space($_course['real_id']);
3656
    $course_max_space = DocumentManager::get_course_quota($_course['code']);
3657
    $total_size = $filesize + $totalSpace;
3658
3659
    if ($total_size > $course_max_space) {
3660
        return [
3661
            'error' => Display::return_message(get_lang('NoSpace'), 'error'),
3662
        ];
3663
    }
3664
3665
    // Compose a unique file name to avoid any conflict
3666
    $new_file_name = api_get_unique_id();
3667
3668
    if ($isCorrection) {
3669
        if (!empty($workInfo['url'])) {
3670
            $new_file_name = basename($workInfo['url']).'_correction';
3671
        } else {
3672
            $new_file_name = $new_file_name.'_correction';
3673
        }
3674
    }
3675
3676
    $curdirpath = basename($my_folder_data['url']);
3677
3678
    // If we come from the group tools the groupid will be saved in $work_table
3679
    if (is_dir($updir.$curdirpath) || empty($curdirpath)) {
3680
        $result = move_uploaded_file(
3681
            $file['tmp_name'],
3682
            $updir.$curdirpath.'/'.$new_file_name
3683
        );
3684
    } else {
3685
        return [
3686
            'error' => Display :: return_message(
3687
                get_lang('FolderDoesntExistsInFileSystem'),
3688
                'error'
3689
            ),
3690
        ];
3691
    }
3692
3693
    if ($result) {
3694
        $url = 'work/'.$curdirpath.'/'.$new_file_name;
3695
    } else {
3696
        return false;
3697
    }
3698
3699
    return [
3700
        'url' => $url,
3701
        'filename' => $filename,
3702
        'filesize' => $filesize,
3703
        'error' => '',
3704
    ];
3705
}
3706
3707
/**
3708
 * Send an e-mail to users related to this work (course teachers, usually, but
3709
 * might include other group members).
3710
 *
3711
 * @param int   $workId
3712
 * @param array $courseInfo
3713
 * @param int   $session_id
3714
 */
3715
function sendAlertToUsers($workId, $courseInfo, $session_id)
3716
{
3717
    $user_list = [];
3718
    $workData = get_work_data_by_id($workId, $courseInfo['real_id'], $session_id);
3719
    // last value is to check this is not "just" an edit
3720
    // YW Tis part serve to send a e-mail to the tutors when a new file is sent
3721
    $send = api_get_course_setting('email_alert_manager_on_new_doc');
3722
3723
    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_TEACHERS) {
3724
        // Lets predefine some variables. Be sure to change the from address!
3725
        if (empty($session_id)) {
3726
            //Teachers
3727
            $user_list = CourseManager::get_user_list_from_course_code(
3728
                api_get_course_id(),
3729
                null,
3730
                null,
3731
                null,
3732
                COURSEMANAGER
3733
            );
3734
        } else {
3735
            // Coaches
3736
            $user_list = CourseManager::get_user_list_from_course_code(
3737
                api_get_course_id(),
3738
                $session_id,
3739
                null,
3740
                null,
3741
                2
3742
            );
3743
        }
3744
    }
3745
3746
    if ($send == SEND_EMAIL_EVERYONE || $send == SEND_EMAIL_STUDENTS) {
3747
        if (!$session_id) {
3748
            $session_id = null;
3749
        }
3750
        $student = CourseManager::get_user_list_from_course_code(
3751
            api_get_course_id(),
3752
            $session_id,
3753
            null,
3754
            null,
3755
            STUDENT,
3756
            null,
3757
            null,
3758
            null,
3759
            null,
3760
            null,
3761
            [api_get_user_id()]
3762
        );
3763
        $user_list = array_merge($user_list, $student);
3764
    }
3765
3766
    if ($send) {
3767
        $subject = "[".api_get_setting('siteName')."] ".get_lang('SendMailBody')."\n ".get_lang('CourseName').": ".$courseInfo['name']."  ";
3768
        foreach ($user_list as $user_data) {
3769
            $to_user_id = $user_data['user_id'];
3770
            $user_info = api_get_user_info($to_user_id);
3771
            $message = get_lang('SendMailBody')."\n".get_lang('CourseName')." : ".$courseInfo['name']."\n";
3772
            $message .= get_lang('UserName')." : ".$user_info['complete_name']."\n";
3773
            $message .= get_lang('DateSent')." : ".api_format_date(api_get_local_time())."\n";
3774
            $url = api_get_path(WEB_CODE_PATH)."work/work.php?cidReq=".$courseInfo['code']."&id_session=".$session_id."&id=".$workData['id'];
3775
            $message .= get_lang('WorkName')." : ".$workData['title']."\n\n".'<a href="'.$url.'">'.get_lang('DownloadLink')."</a>\n";
3776
            MessageManager::send_message_simple(
3777
                $to_user_id,
3778
                $subject,
3779
                $message,
3780
                0,
3781
                false,
3782
                false,
3783
                [],
3784
                false
3785
            );
3786
        }
3787
    }
3788
}
3789
3790
/**
3791
 * Check if the current uploaded work filename already exists in the current assement.
3792
 *
3793
 * @param string $filename
3794
 * @param int    $workId
3795
 *
3796
 * @return array
3797
 */
3798
function checkExistingWorkFileName($filename, $workId)
3799
{
3800
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3801
    $filename = Database::escape_string($filename);
3802
    $workId = (int) $workId;
3803
3804
    $sql = "SELECT title FROM $table
3805
            WHERE parent_id = $workId AND title = '$filename' AND active = 1";
3806
    $result = Database::query($sql);
3807
3808
    return Database::fetch_assoc($result);
3809
}
3810
3811
/**
3812
 * @param array $workInfo
3813
 * @param array $values
3814
 * @param array $courseInfo
3815
 * @param int   $sessionId
3816
 * @param int   $groupId
3817
 * @param int   $userId
3818
 * @param array $file
3819
 * @param bool  $checkDuplicated
3820
 * @param bool  $showFlashMessage
3821
 *
3822
 * @return null|string
3823
 */
3824
function processWorkForm(
3825
    $workInfo,
3826
    $values,
3827
    $courseInfo,
3828
    $sessionId,
3829
    $groupId,
3830
    $userId,
3831
    $file = [],
3832
    $checkDuplicated = false,
3833
    $showFlashMessage = true
3834
) {
3835
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
3836
3837
    $courseId = $courseInfo['real_id'];
3838
    $groupId = (int) $groupId;
3839
    $sessionId = (int) $sessionId;
3840
    $userId = (int) $userId;
3841
3842
    $extension = '';
3843
    if (isset($values['extension'])) {
3844
        $extension = $values['extension'];
3845
    } else {
3846
        $fileInfo = pathinfo($values['title']);
3847
        if (isset($fileInfo['extension']) && !empty($fileInfo['extension'])) {
3848
            $extension = '.'.$fileInfo['extension'];
3849
            $values['title'] = $fileInfo['filename'];
3850
        }
3851
    }
3852
3853
    $title = $values['title'].$extension;
3854
    $description = isset($values['description']) ? $values['description'] : '';
3855
    $containsFile = isset($values['contains_file']) && !empty($values['contains_file']) ? (int) $values['contains_file'] : 0;
3856
3857
    $saveWork = true;
3858
    $filename = null;
3859
    $url = null;
3860
    $filesize = null;
3861
    $workData = [];
3862
    $message = null;
3863
3864
    if ($containsFile) {
3865
        $saveWork = false;
3866
        if ($checkDuplicated) {
3867
            if (checkExistingWorkFileName($file['name'], $workInfo['id'])) {
3868
                $saveWork = false;
3869
                $result['error'] = get_lang('YouAlreadySentThisFile');
3870
                $workData['error'] = get_lang('UplAlreadyExists');
3871
            } else {
3872
                $result = uploadWork($workInfo, $courseInfo, false, [], $file);
3873
            }
3874
        } else {
3875
            $result = uploadWork($workInfo, $courseInfo, false, [], $file);
3876
        }
3877
3878
        if (isset($result['error'])) {
3879
            $saveWork = false;
3880
            if ($showFlashMessage) {
3881
                $message = $result['error'];
3882
            }
3883
            if (empty($result['error']) && isset($result['url']) && !empty($result['url'])) {
3884
                $saveWork = true;
3885
            }
3886
        }
3887
    }
3888
3889
    if ($saveWork) {
3890
        $filename = isset($result['filename']) ? $result['filename'] : null;
3891
        if (empty($title)) {
3892
            $title = isset($result['title']) && !empty($result['title']) ? $result['title'] : get_lang('Untitled');
3893
        }
3894
        $filesize = isset($result['filesize']) ? $result['filesize'] : null;
3895
        $url = isset($result['url']) ? $result['url'] : null;
3896
    }
3897
3898
    if (empty($title)) {
3899
        $title = get_lang('Untitled');
3900
    }
3901
3902
    $groupIid = 0;
3903
    $groupInfo = [];
3904
    if ($groupId) {
3905
        $groupInfo = GroupManager::get_group_properties($groupId);
3906
        $groupIid = $groupInfo['iid'];
3907
    }
3908
3909
    if ($saveWork) {
3910
        $active = '1';
3911
        $params = [
3912
            'c_id' => $courseId,
3913
            'url' => $url,
3914
            'filetype' => 'file',
3915
            'title' => $title,
3916
            'description' => $description,
3917
            'contains_file' => $containsFile,
3918
            'active' => $active,
3919
            'accepted' => '1',
3920
            'qualificator_id' => 0,
3921
            'document_id' => 0,
3922
            'weight' => 0,
3923
            'allow_text_assignment' => 0,
3924
            'post_group_id' => $groupIid,
3925
            'sent_date' => api_get_utc_datetime(),
3926
            'parent_id' => $workInfo['id'],
3927
            'session_id' => $sessionId ? $sessionId : null,
3928
            'user_id' => $userId,
3929
            'has_properties' => 0,
3930
            'qualification' => 0,
3931
            //'filesize' => $filesize
3932
        ];
3933
        $workId = Database::insert($work_table, $params);
3934
3935
        if ($workId) {
3936
            $sql = "UPDATE $work_table SET id = iid WHERE iid = $workId ";
3937
            Database::query($sql);
3938
3939
            if (array_key_exists('filename', $workInfo) && !empty($filename)) {
3940
                $filename = Database::escape_string($filename);
3941
                $sql = "UPDATE $work_table SET
3942
                            filename = '$filename'
3943
                        WHERE iid = $workId";
3944
                Database::query($sql);
3945
            }
3946
3947
            if (array_key_exists('document_id', $workInfo)) {
3948
                $documentId = isset($values['document_id']) ? intval($values['document_id']) : 0;
3949
                $sql = "UPDATE $work_table SET
3950
                            document_id = '$documentId'
3951
                        WHERE iid = $workId";
3952
                Database::query($sql);
3953
            }
3954
            api_item_property_update(
3955
                $courseInfo,
3956
                'work',
3957
                $workId,
3958
                'DocumentAdded',
3959
                $userId,
3960
                $groupInfo
3961
            );
3962
            sendAlertToUsers($workId, $courseInfo, $sessionId);
3963
            Event::event_upload($workId);
3964
3965
            // The following feature requires the creation of a work-type
3966
            // extra_field and the following setting in the configuration file
3967
            // (until moved to the database). It allows te teacher to set a
3968
            // "considered work time", meaning the time we assume a student
3969
            // would have spent, approximately, to prepare the task before
3970
            // handing it in Chamilo, adding this time to the student total
3971
            // course use time, as a register of time spent *before* his
3972
            // connection to the platform to hand the work in.
3973
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
3974
3975
            if (!empty($consideredWorkingTime)) {
3976
                // Get the "considered work time" defined for this work
3977
                $fieldValue = new ExtraFieldValue('work');
3978
                $resultExtra = $fieldValue->getAllValuesForAnItem(
3979
                    $workInfo['iid'], //the ID of the work *folder*, not the document uploaded by the student
3980
                    true
3981
                );
3982
3983
                $workingTime = null;
3984
                foreach ($resultExtra as $field) {
3985
                    $field = $field['value'];
3986
                    if ($consideredWorkingTime == $field->getField()->getVariable()) {
3987
                        $workingTime = $field->getValue();
3988
                    }
3989
                }
3990
3991
                // If no time was defined, or a time of "0" was set, do nothing
3992
                if (!empty($workingTime)) {
3993
                    // If some time is set, get the list of docs handed in by
3994
                    // this student (to make sure we count the time only once)
3995
                    $userWorks = get_work_user_list(
3996
                        0,
3997
                        100,
3998
                        null,
3999
                        null,
4000
                        $workInfo['id'],
4001
                        null,
4002
                        $userId,
4003
                        false,
4004
                        $courseId,
4005
                        $sessionId
4006
                    );
4007
4008
                    if (count($userWorks) == 1) {
4009
                        // The student only uploaded one doc so far, so add the
4010
                        // considered work time to his course connection time
4011
                        $ip = api_get_real_ip();
4012
                        Event::eventAddVirtualCourseTime($courseId, $userId, $sessionId, $workingTime, $ip);
4013
                    }
4014
                }
4015
            }
4016
            $workData = get_work_data_by_id($workId);
4017
            if ($workData && $showFlashMessage) {
4018
                Display::addFlash(Display::return_message(get_lang('DocAdd')));
4019
            }
4020
        }
4021
    } else {
4022
        if ($showFlashMessage) {
4023
            Display::addFlash(
4024
                Display::return_message(
4025
                    $message ? $message : get_lang('ImpossibleToSaveTheDocument'),
4026
                    'error'
4027
                )
4028
            );
4029
        }
4030
    }
4031
4032
    return $workData;
4033
}
4034
4035
/**
4036
 * Creates a new task (directory) in the assignment tool.
4037
 *
4038
 * @param array $formValues
4039
 * @param int   $user_id
4040
 * @param array $courseInfo
4041
 * @param int   $groupId
4042
 * @param int   $sessionId
4043
 *
4044
 * @return bool|int
4045
 * @note $params can have the following elements, but should at least have the 2 first ones: (
4046
 *       'new_dir' => 'some-name',
4047
 *       'description' => 'some-desc',
4048
 *       'qualification' => 20 (e.g. 20),
4049
 *       'weight' => 50 (percentage) to add to gradebook (e.g. 50),
4050
 *       'allow_text_assignment' => 0/1/2,
4051
 *
4052
 * @todo Rename createAssignment or createWork, or something like that
4053
 */
4054
function addDir($formValues, $user_id, $courseInfo, $groupId, $sessionId = 0)
4055
{
4056
    $em = Database::getManager();
4057
4058
    $user_id = (int) $user_id;
4059
    $groupId = (int) $groupId;
4060
    $sessionId = (int) $sessionId;
4061
4062
    $groupIid = 0;
4063
    $groupInfo = [];
4064
    if (!empty($groupId)) {
4065
        $groupInfo = GroupManager::get_group_properties($groupId);
4066
        $groupIid = $groupInfo['iid'];
4067
    }
4068
    $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
4069
4070
    $base_work_dir = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work';
4071
    $course_id = $courseInfo['real_id'];
4072
4073
    $directory = api_replace_dangerous_char($formValues['new_dir']);
4074
    $directory = disable_dangerous_file($directory);
4075
4076
    $created_dir = create_unexisting_work_directory($base_work_dir, $directory);
4077
4078
    if (empty($created_dir)) {
4079
        return false;
4080
    }
4081
4082
    $enableEndDate = isset($formValues['enableEndDate']) ? true : false;
4083
    $enableExpiryDate = isset($formValues['enableExpiryDate']) ? true : false;
4084
4085
    if ($enableEndDate && $enableExpiryDate) {
4086
        if ($formValues['expires_on'] > $formValues['ends_on']) {
4087
            Display::addFlash(
4088
                Display::return_message(
4089
                    get_lang('DateExpiredNotBeLessDeadLine'),
4090
                    'warning'
4091
                )
4092
            );
4093
4094
            return false;
4095
        }
4096
    }
4097
4098
    $dirName = '/'.$created_dir;
4099
    $today = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
4100
    $title = isset($formValues['work_title']) ? $formValues['work_title'] : $formValues['new_dir'];
4101
4102
    $workTable = new CStudentPublication();
4103
    $workTable
4104
        ->setCId($course_id)
4105
        ->setUrl($dirName)
4106
        ->setTitle($title)
4107
        ->setDescription($formValues['description'])
4108
        ->setActive(true)
4109
        ->setAccepted(true)
4110
        ->setFiletype('folder')
4111
        ->setPostGroupId($groupIid)
4112
        ->setSentDate($today)
4113
        ->setQualification($formValues['qualification'] != '' ? $formValues['qualification'] : 0)
4114
        ->setParentId(0)
4115
        ->setQualificatorId(0)
4116
        ->setWeight(!empty($formValues['weight']) ? $formValues['weight'] : 0)
4117
        ->setSession($session)
4118
        ->setAllowTextAssignment($formValues['allow_text_assignment'])
4119
        ->setContainsFile(0)
4120
        ->setUserId($user_id)
4121
        ->setHasProperties(0)
4122
        ->setDocumentId(0);
4123
4124
    $em->persist($workTable);
4125
    $em->flush();
4126
4127
    $workTable->setId($workTable->getIid());
4128
    $em->merge($workTable);
4129
    $em->flush();
4130
4131
    // Folder created
4132
    api_item_property_update(
4133
        $courseInfo,
4134
        'work',
4135
        $workTable->getIid(),
4136
        'DirectoryCreated',
4137
        $user_id,
4138
        $groupInfo
4139
    );
4140
4141
    updatePublicationAssignment(
4142
        $workTable->getIid(),
4143
        $formValues,
4144
        $courseInfo,
4145
        $groupIid
4146
    );
4147
4148
    // Added the new Work ID to the extra field values
4149
    $formValues['item_id'] = $workTable->getIid();
4150
4151
    $workFieldValue = new ExtraFieldValue('work');
4152
    $workFieldValue->saveFieldValues($formValues);
4153
4154
    $sendEmailAlert = api_get_course_setting('email_alert_students_on_new_homework');
4155
4156
    switch ($sendEmailAlert) {
4157
        case 1:
4158
            sendEmailToStudentsOnHomeworkCreation(
4159
                $workTable->getIid(),
4160
                $course_id,
4161
                $sessionId
4162
            );
4163
            //no break
4164
        case 2:
4165
            sendEmailToDrhOnHomeworkCreation(
4166
                $workTable->getIid(),
4167
                $course_id,
4168
                $sessionId
4169
            );
4170
            break;
4171
    }
4172
4173
    return $workTable->getIid();
4174
}
4175
4176
/**
4177
 * @param int   $workId
4178
 * @param array $courseInfo
4179
 *
4180
 * @return int
4181
 */
4182
function agendaExistsForWork($workId, $courseInfo)
4183
{
4184
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
4185
    $courseId = $courseInfo['real_id'];
4186
    $workId = intval($workId);
4187
4188
    $sql = "SELECT add_to_calendar FROM $workTable
4189
            WHERE c_id = $courseId AND publication_id = ".$workId;
4190
    $res = Database::query($sql);
4191
    if (Database::num_rows($res)) {
4192
        $row = Database::fetch_array($res, 'ASSOC');
4193
        if (!empty($row['add_to_calendar'])) {
4194
            return $row['add_to_calendar'];
4195
        }
4196
    }
4197
4198
    return 0;
4199
}
4200
4201
/**
4202
 * Update work description, qualification, weight, allow_text_assignment.
4203
 *
4204
 * @param int   $workId     (iid)
4205
 * @param array $params
4206
 * @param array $courseInfo
4207
 * @param int   $sessionId
4208
 */
4209
function updateWork($workId, $params, $courseInfo, $sessionId = 0)
4210
{
4211
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4212
    $filteredParams = [
4213
        'description' => $params['description'],
4214
        'qualification' => $params['qualification'],
4215
        'weight' => $params['weight'],
4216
        'allow_text_assignment' => $params['allow_text_assignment'],
4217
    ];
4218
4219
    Database::update(
4220
        $workTable,
4221
        $filteredParams,
4222
        [
4223
            'iid = ? AND c_id = ?' => [
4224
                $workId,
4225
                $courseInfo['real_id'],
4226
            ],
4227
        ]
4228
    );
4229
4230
    $workFieldValue = new ExtraFieldValue('work');
4231
    $workFieldValue->saveFieldValues($params);
4232
}
4233
4234
/**
4235
 * @param int   $workId
4236
 * @param array $params
4237
 * @param array $courseInfo
4238
 * @param int   $groupId
4239
 */
4240
function updatePublicationAssignment($workId, $params, $courseInfo, $groupId)
4241
{
4242
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
4243
    $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4244
    $workId = intval($workId);
4245
    $now = api_get_utc_datetime();
4246
    $course_id = $courseInfo['real_id'];
4247
4248
    // Insert into agenda
4249
    $agendaId = 0;
4250
    if (isset($params['add_to_calendar']) && $params['add_to_calendar'] == 1) {
4251
        // Setting today date
4252
        $date = $end_date = $now;
4253
4254
        if (isset($params['enableExpiryDate'])) {
4255
            $end_date = $params['expires_on'];
4256
            $date = $end_date;
4257
        }
4258
4259
        $title = sprintf(get_lang('HandingOverOfTaskX'), $params['new_dir']);
4260
        $description = isset($params['description']) ? $params['description'] : '';
4261
        $content = '<a href="'.api_get_path(WEB_CODE_PATH).'work/work_list.php?'.api_get_cidreq().'&id='.$workId.'">'
4262
            .$params['new_dir'].'</a>'.$description;
4263
4264
        $agendaId = agendaExistsForWork($workId, $courseInfo);
4265
4266
        // Add/edit agenda
4267
        $agenda = new Agenda('course');
4268
        $agenda->set_course($courseInfo);
4269
4270
        if (!empty($agendaId)) {
4271
            // add_to_calendar is set but it doesnt exists then invalidate
4272
            $eventInfo = $agenda->get_event($agendaId);
4273
            if (empty($eventInfo)) {
4274
                $agendaId = 0;
4275
            }
4276
        }
4277
4278
        $eventColor = $agenda->eventStudentPublicationColor;
4279
4280
        if (empty($agendaId)) {
4281
            $agendaId = $agenda->addEvent(
4282
                $date,
4283
                $end_date,
4284
                'false',
4285
                $title,
4286
                $content,
4287
                ['GROUP:'.$groupId],
4288
                false,
4289
                null,
4290
                [],
4291
                [],
4292
                null,
4293
                $eventColor
4294
            );
4295
        } else {
4296
            $agenda->editEvent(
4297
                $agendaId,
4298
                $end_date,
4299
                $end_date,
4300
                'false',
4301
                $title,
4302
                $content,
4303
                [],
4304
                [],
4305
                [],
4306
                null,
4307
                $eventColor
4308
            );
4309
        }
4310
    }
4311
4312
    $qualification = isset($params['qualification']) && !empty($params['qualification']) ? 1 : 0;
4313
    $expiryDate = isset($params['enableExpiryDate']) && (int) $params['enableExpiryDate'] == 1 ? api_get_utc_datetime($params['expires_on']) : '';
4314
    $endDate = isset($params['enableEndDate']) && (int) $params['enableEndDate'] == 1 ? api_get_utc_datetime($params['ends_on']) : '';
4315
    $data = get_work_assignment_by_id($workId, $course_id);
4316
    if (!empty($expiryDate)) {
4317
        $expiryDateCondition = "expires_on = '".Database::escape_string($expiryDate)."', ";
4318
    } else {
4319
        $expiryDateCondition = "expires_on = null, ";
4320
    }
4321
4322
    if (!empty($endDate)) {
4323
        $endOnCondition = "ends_on = '".Database::escape_string($endDate)."', ";
4324
    } else {
4325
        $endOnCondition = "ends_on = null, ";
4326
    }
4327
4328
    if (empty($data)) {
4329
        $sql = "INSERT INTO $table SET
4330
                c_id = $course_id ,
4331
                $expiryDateCondition
4332
                $endOnCondition
4333
                add_to_calendar = $agendaId,
4334
                enable_qualification = '$qualification',
4335
                publication_id = '$workId'";
4336
        Database::query($sql);
4337
        $my_last_id = Database::insert_id();
4338
4339
        if ($my_last_id) {
4340
            $sql = "UPDATE $table SET
4341
                        id = iid
4342
                    WHERE iid = $my_last_id";
4343
            Database::query($sql);
4344
4345
            $sql = "UPDATE $workTable SET
4346
                        has_properties  = $my_last_id,
4347
                        view_properties = 1
4348
                    WHERE c_id = $course_id AND id = $workId";
4349
            Database::query($sql);
4350
        }
4351
    } else {
4352
        $sql = "UPDATE $table SET
4353
                    $expiryDateCondition
4354
                    $endOnCondition
4355
                    add_to_calendar  = $agendaId,
4356
                    enable_qualification = '".$qualification."'
4357
                WHERE
4358
                    publication_id = $workId AND
4359
                    c_id = $course_id AND
4360
                    iid = ".$data['iid'];
4361
        Database::query($sql);
4362
    }
4363
4364
    if (!empty($params['category_id'])) {
4365
        $link_info = GradebookUtils::isResourceInCourseGradebook(
4366
            $courseInfo['code'],
4367
            LINK_STUDENTPUBLICATION,
4368
            $workId,
4369
            api_get_session_id()
4370
        );
4371
4372
        $linkId = null;
4373
        if (!empty($link_info)) {
4374
            $linkId = $link_info['id'];
4375
        }
4376
4377
        if (isset($params['make_calification']) &&
4378
            $params['make_calification'] == 1
4379
        ) {
4380
            if (empty($linkId)) {
4381
                GradebookUtils::add_resource_to_course_gradebook(
4382
                    $params['category_id'],
4383
                    $courseInfo['code'],
4384
                    LINK_STUDENTPUBLICATION,
4385
                    $workId,
4386
                    $params['new_dir'],
4387
                    api_float_val($params['weight']),
4388
                    api_float_val($params['qualification']),
4389
                    $params['description'],
4390
                    1,
4391
                    api_get_session_id()
4392
                );
4393
            } else {
4394
                GradebookUtils::updateResourceFromCourseGradebook(
4395
                    $linkId,
4396
                    $courseInfo['code'],
4397
                    $params['weight']
4398
                );
4399
            }
4400
        } else {
4401
            // Delete everything of the gradebook for this $linkId
4402
            GradebookUtils::remove_resource_from_course_gradebook($linkId);
4403
        }
4404
    }
4405
}
4406
4407
/**
4408
 * Delete all work by student.
4409
 *
4410
 * @param int   $userId
4411
 * @param array $courseInfo
4412
 *
4413
 * @return array return deleted items
4414
 */
4415
function deleteAllWorkPerUser($userId, $courseInfo)
4416
{
4417
    $deletedItems = [];
4418
    $workPerUser = getWorkPerUser($userId);
4419
    if (!empty($workPerUser)) {
4420
        foreach ($workPerUser as $work) {
4421
            $work = $work['work'];
4422
            foreach ($work->user_results as $userResult) {
4423
                $result = deleteWorkItem($userResult['id'], $courseInfo);
4424
                if ($result) {
4425
                    $deletedItems[] = $userResult;
4426
                }
4427
            }
4428
        }
4429
    }
4430
4431
    return $deletedItems;
4432
}
4433
4434
/**
4435
 * @param int $item_id
4436
 * @param array course info
4437
 *
4438
 * @return bool
4439
 */
4440
function deleteWorkItem($item_id, $courseInfo)
4441
{
4442
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4443
    $TSTDPUBASG = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
4444
    $currentCourseRepositorySys = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
4445
    $is_allowed_to_edit = api_is_allowed_to_edit();
4446
    $file_deleted = false;
4447
    $item_id = intval($item_id);
4448
4449
    $is_author = user_is_author($item_id);
4450
    $work_data = get_work_data_by_id($item_id);
4451
    $locked = api_resource_is_locked_by_gradebook($work_data['parent_id'], LINK_STUDENTPUBLICATION);
4452
    $course_id = $courseInfo['real_id'];
4453
4454
    if (($is_allowed_to_edit && $locked == false) ||
4455
        (
4456
            $locked == false &&
4457
            $is_author &&
4458
            api_get_course_setting('student_delete_own_publication') == 1 &&
4459
            $work_data['qualificator_id'] == 0
4460
        )
4461
    ) {
4462
        // We found the current user is the author
4463
        $sql = "SELECT url, contains_file, user_id, session_id, parent_id 
4464
                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
            // If the "considered_working_time" option is enabled, check
4472
            // whether some time should be removed from track_e_course_access
4473
            $consideredWorkingTime = api_get_configuration_value('considered_working_time');
4474
            if ($consideredWorkingTime) {
4475
                $userWorks = get_work_user_list(
4476
                    0,
4477
                    100,
4478
                    null,
4479
                    null,
4480
                    $row['parent_id'],
4481
                    null,
4482
                    $row['user_id'],
4483
                    false,
4484
                    $course_id,
4485
                    $row['session_id']
4486
                );
4487
                // We're only interested in deleting the time if this is the latest work sent
4488
                if (count($userWorks) == 1) {
4489
                    // Get the "considered work time" defined for this work
4490
                    $fieldValue = new ExtraFieldValue('work');
4491
                    $resultExtra = $fieldValue->getAllValuesForAnItem(
4492
                        $row['parent_id'],
4493
                        true
4494
                    );
4495
4496
                    $workingTime = null;
4497
                    foreach ($resultExtra as $field) {
4498
                        $field = $field['value'];
4499
4500
                        if ($consideredWorkingTime == $field->getField()->getVariable()) {
4501
                            $workingTime = $field->getValue();
4502
                        }
4503
                    }
4504
                    // If no time was defined, or a time of "0" was set, do nothing
4505
                    if (!empty($workingTime)) {
4506
                        $sessionId = empty($row['session_id']) ? 0 : $row['session_id'];
4507
                        // Getting false from the following call would mean the
4508
                        // time record
4509
                        Event::eventRemoveVirtualCourseTime(
4510
                            $course_id,
4511
                            $row['user_id'],
4512
                            $sessionId,
4513
                            $workingTime
4514
                        );
4515
                    }
4516
                }
4517
            } // end of considered_working_time check section
4518
4519
            $sql = "UPDATE $work_table SET active = 2
4520
                    WHERE c_id = $course_id AND id = $item_id";
4521
            Database::query($sql);
4522
            $sql = "DELETE FROM $TSTDPUBASG
4523
                    WHERE c_id = $course_id AND publication_id = $item_id";
4524
            Database::query($sql);
4525
4526
            api_item_property_update(
4527
                $courseInfo,
4528
                'work',
4529
                $item_id,
4530
                'DocumentDeleted',
4531
                api_get_user_id()
4532
            );
4533
4534
            Event::addEvent(
4535
                LOG_WORK_FILE_DELETE,
4536
                LOG_WORK_DATA,
4537
                [
4538
                    'id' => $work_data['id'],
4539
                    'url' => $work_data['url'],
4540
                    'title' => $work_data['title'],
4541
                ],
4542
                null,
4543
                api_get_user_id(),
4544
                api_get_course_int_id(),
4545
                api_get_session_id()
4546
            );
4547
4548
            $work = $row['url'];
4549
4550
            if ($row['contains_file'] == 1) {
4551
                if (!empty($work)) {
4552
                    if (api_get_setting('permanently_remove_deleted_files') === 'true') {
4553
                        my_delete($currentCourseRepositorySys.'/'.$work);
4554
                        $file_deleted = true;
4555
                    } else {
4556
                        $extension = pathinfo($work, PATHINFO_EXTENSION);
4557
                        $new_dir = $work.'_DELETED_'.$item_id.'.'.$extension;
4558
4559
                        if (file_exists($currentCourseRepositorySys.'/'.$work)) {
4560
                            rename($currentCourseRepositorySys.'/'.$work, $currentCourseRepositorySys.'/'.$new_dir);
4561
                            $file_deleted = true;
4562
                        }
4563
                    }
4564
                }
4565
            } else {
4566
                $file_deleted = true;
4567
            }
4568
        }
4569
    }
4570
4571
    return $file_deleted;
4572
}
4573
4574
/**
4575
 * @param FormValidator $form
4576
 * @param array         $defaults
4577
 * @param int           $workId
4578
 *
4579
 * @return FormValidator
4580
 */
4581
function getFormWork($form, $defaults = [], $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
            [
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
    $extraField = new ExtraField('work');
4675
    $extra = $extraField->addElements($form, $workId);
4676
4677
    $htmlHeadXtra[] = '
4678
        <script>
4679
        $(function() {
4680
            '.$extra['jquery_ready_content'].'
4681
        });
4682
        </script>';
4683
4684
    $form->addHtml('</div>');
4685
4686
    $skillList = Skill::addSkillsToForm($form, ITEM_TYPE_STUDENT_PUBLICATION, $workId);
4687
4688
    if (!empty($defaults)) {
4689
        $defaults['skills'] = array_keys($skillList);
4690
        $form->setDefaults($defaults);
4691
    }
4692
4693
    return $form;
4694
}
4695
4696
/**
4697
 * @return array
4698
 */
4699
function getUploadDocumentType()
4700
{
4701
    return [
4702
        0 => get_lang('AllowFileOrText'),
4703
        1 => get_lang('AllowOnlyText'),
4704
        2 => get_lang('AllowOnlyFiles'),
4705
    ];
4706
}
4707
4708
/**
4709
 * @param int   $item_id
4710
 * @param array $course_info
4711
 *
4712
 * @return bool
4713
 */
4714
function makeVisible($item_id, $course_info)
4715
{
4716
    if (empty($course_info) || empty($item_id)) {
4717
        return false;
4718
    }
4719
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4720
    $course_id = $course_info['real_id'];
4721
    $item_id = intval($item_id);
4722
4723
    $sql = "UPDATE $work_table SET accepted = 1
4724
            WHERE c_id = $course_id AND id = $item_id";
4725
    Database::query($sql);
4726
    api_item_property_update($course_info, 'work', $item_id, 'visible', api_get_user_id());
4727
4728
    return true;
4729
}
4730
4731
/**
4732
 * @param int   $item_id
4733
 * @param array $course_info
4734
 *
4735
 * @return int
4736
 */
4737
function makeInvisible($item_id, $course_info)
4738
{
4739
    if (empty($course_info) || empty($item_id)) {
4740
        return false;
4741
    }
4742
4743
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4744
    $item_id = intval($item_id);
4745
    $course_id = $course_info['real_id'];
4746
    $sql = "UPDATE $table
4747
            SET accepted = 0
4748
            WHERE c_id = $course_id AND id = '".$item_id."'";
4749
    Database::query($sql);
4750
    api_item_property_update(
4751
        $course_info,
4752
        'work',
4753
        $item_id,
4754
        'invisible',
4755
        api_get_user_id()
4756
    );
4757
4758
    return true;
4759
}
4760
4761
/**
4762
 * @param int    $item_id
4763
 * @param string $path
4764
 * @param array  $courseInfo
4765
 * @param int    $groupId    iid
4766
 * @param int    $sessionId
4767
 *
4768
 * @return string
4769
 */
4770
function generateMoveForm($item_id, $path, $courseInfo, $groupId, $sessionId)
4771
{
4772
    $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
4773
    $courseId = $courseInfo['real_id'];
4774
    $folders = [];
4775
    $session_id = intval($sessionId);
4776
    $groupId = intval($groupId);
4777
    $sessionCondition = empty($sessionId) ? " AND (session_id = 0 OR session_id IS NULL) " : " AND session_id='".$session_id."'";
4778
4779
    $groupIid = 0;
4780
    if ($groupId) {
4781
        $groupInfo = GroupManager::get_group_properties($groupId);
4782
        $groupIid = $groupInfo['iid'];
4783
    }
4784
4785
    $sql = "SELECT id, url, title
4786
            FROM $work_table
4787
            WHERE
4788
                c_id = $courseId AND
4789
                active IN (0, 1) AND
4790
                url LIKE '/%' AND
4791
                post_group_id = $groupIid
4792
                $sessionCondition";
4793
    $res = Database::query($sql);
4794
    while ($folder = Database::fetch_array($res)) {
4795
        $title = empty($folder['title']) ? basename($folder['url']) : $folder['title'];
4796
        $folders[$folder['id']] = $title;
4797
    }
4798
4799
    return build_work_move_to_selector($folders, $path, $item_id);
4800
}
4801
4802
/**
4803
 * @param int $workId
4804
 *
4805
 * @return string
4806
 */
4807
function showStudentList($workId)
4808
{
4809
    $columnModel = [
4810
        [
4811
            'name' => 'student',
4812
            'index' => 'student',
4813
            'width' => '350px',
4814
            'align' => 'left',
4815
            'sortable' => 'false',
4816
        ],
4817
        [
4818
            'name' => 'works',
4819
            'index' => 'works',
4820
            'align' => 'center',
4821
            'sortable' => 'false',
4822
        ],
4823
    ];
4824
    $token = null;
4825
    $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_work_student_list_overview&work_id='.$workId.'&'.api_get_cidreq();
4826
4827
    $columns = [
4828
        get_lang('Students'),
4829
        get_lang('Works'),
4830
    ];
4831
4832
    $order = api_is_western_name_order() ? 'firstname' : 'lastname';
4833
    $params = [
4834
        'autowidth' => 'true',
4835
        'height' => 'auto',
4836
        'rowNum' => 5,
4837
        'sortname' => $order,
4838
        'sortorder' => 'asc',
4839
    ];
4840
4841
    $html = '<script>
4842
    $(function() {
4843
        '.Display::grid_js('studentList', $url, $columns, $columnModel, $params, [], null, true).'
4844
        $("#workList").jqGrid(
4845
            "navGrid",
4846
            "#studentList_pager",
4847
            { edit: false, add: false, del: false },
4848
            { height:280, reloadAfterSubmit:false }, // edit options
4849
            { height:280, reloadAfterSubmit:false }, // add options
4850
            { width:500 } // search options
4851
        );
4852
    });
4853
    </script>';
4854
    $html .= Display::grid_html('studentList');
4855
4856
    return $html;
4857
}
4858
4859
/**
4860
 * @param string $courseCode
4861
 * @param int    $sessionId
4862
 * @param int    $groupId
4863
 * @param int    $start
4864
 * @param int    $limit
4865
 * @param string $sidx
4866
 * @param string $sord
4867
 * @param $getCount
4868
 *
4869
 * @return array|int
4870
 */
4871
function getWorkUserList($courseCode, $sessionId, $groupId, $start, $limit, $sidx, $sord, $getCount = false)
4872
{
4873
    if (!empty($groupId)) {
4874
        $userList = GroupManager::get_users(
4875
            $groupId,
4876
            false,
4877
            $start,
4878
            $limit,
4879
            $getCount,
4880
            null,
4881
            $sidx,
4882
            $sord
4883
        );
4884
    } else {
4885
        $limitString = null;
4886
        if (!empty($start) && !empty($limit)) {
4887
            $start = intval($start);
4888
            $limit = intval($limit);
4889
            $limitString = " LIMIT $start, $limit";
4890
        }
4891
4892
        $orderBy = null;
4893
4894
        if (!empty($sidx) && !empty($sord)) {
4895
            if (in_array($sidx, ['firstname', 'lastname'])) {
4896
                $orderBy = "ORDER BY $sidx $sord";
4897
            }
4898
        }
4899
4900
        if (empty($sessionId)) {
4901
            $userList = CourseManager::get_user_list_from_course_code(
4902
                $courseCode,
4903
                $sessionId,
4904
                $limitString,
4905
                $orderBy,
4906
                STUDENT,
4907
                $getCount
4908
            );
4909
        } else {
4910
            $userList = CourseManager::get_user_list_from_course_code(
4911
                $courseCode,
4912
                $sessionId,
4913
                $limitString,
4914
                $orderBy,
4915
                0,
4916
                $getCount
4917
            );
4918
        }
4919
4920
        if ($getCount == false) {
4921
            $userList = array_keys($userList);
4922
        }
4923
    }
4924
4925
    return $userList;
4926
}
4927
4928
/**
4929
 * @param int    $workId
4930
 * @param string $courseCode
4931
 * @param int    $sessionId
4932
 * @param int    $groupId
4933
 * @param int    $start
4934
 * @param int    $limit
4935
 * @param int    $sidx
4936
 * @param string $sord
4937
 * @param bool   $getCount
4938
 *
4939
 * @return array|int
4940
 */
4941
function getWorkUserListData(
4942
    $workId,
4943
    $courseCode,
4944
    $sessionId,
4945
    $groupId,
4946
    $start,
4947
    $limit,
4948
    $sidx,
4949
    $sord,
4950
    $getCount = false
4951
) {
4952
    $my_folder_data = get_work_data_by_id($workId);
4953
    $workParents = [];
4954
    if (empty($my_folder_data)) {
4955
        $workParents = getWorkList($workId, $my_folder_data, null);
4956
    }
4957
4958
    $workIdList = [];
4959
    if (!empty($workParents)) {
4960
        foreach ($workParents as $work) {
4961
            $workIdList[] = $work->id;
4962
        }
4963
    }
4964
4965
    $courseInfo = api_get_course_info($courseCode);
4966
4967
    $userList = getWorkUserList(
4968
        $courseCode,
4969
        $sessionId,
4970
        $groupId,
4971
        $start,
4972
        $limit,
4973
        $sidx,
4974
        $sord,
4975
        $getCount
4976
    );
4977
4978
    if ($getCount) {
4979
        return $userList;
4980
    }
4981
    $results = [];
4982
    if (!empty($userList)) {
4983
        foreach ($userList as $userId) {
4984
            $user = api_get_user_info($userId);
4985
            $link = api_get_path(WEB_CODE_PATH).'work/student_work.php?'.api_get_cidreq().'&studentId='.$user['user_id'];
4986
            $url = Display::url(api_get_person_name($user['firstname'], $user['lastname']), $link);
4987
            $userWorks = 0;
4988
            if (!empty($workIdList)) {
4989
                $userWorks = getUniqueStudentAttempts(
4990
                    $workIdList,
4991
                    $groupId,
4992
                    $courseInfo['real_id'],
4993
                    $sessionId,
4994
                    $user['user_id']
4995
                );
4996
            }
4997
            $works = $userWorks." / ".count($workParents);
4998
            $results[] = [
4999
                'student' => $url,
5000
                'works' => Display::url($works, $link),
5001
            ];
5002
        }
5003
    }
5004
5005
    return $results;
5006
}
5007
5008
/**
5009
 * @param int   $id
5010
 * @param array $course_info
5011
 * @param bool  $isCorrection
5012
 *
5013
 * @return bool
5014
 */
5015
function downloadFile($id, $course_info, $isCorrection)
5016
{
5017
    return getFile($id, $course_info, true, $isCorrection, true);
5018
}
5019
5020
/**
5021
 * @param int   $id
5022
 * @param array $course_info
5023
 * @param bool  $download
5024
 * @param bool  $isCorrection
5025
 * @param bool  $forceAccessForCourseAdmins
5026
 *
5027
 * @return bool
5028
 */
5029
function getFile($id, $course_info, $download = true, $isCorrection = false, $forceAccessForCourseAdmins = false)
5030
{
5031
    $file = getFileContents($id, $course_info, 0, $isCorrection, $forceAccessForCourseAdmins);
5032
    if (!empty($file) && is_array($file)) {
5033
        return DocumentManager::file_send_for_download(
5034
            $file['path'],
5035
            $download,
5036
            $file['title']
5037
        );
5038
    }
5039
5040
    return false;
5041
}
5042
5043
/**
5044
 * Get the file contents for an assigment.
5045
 *
5046
 * @param int   $id
5047
 * @param array $courseInfo
5048
 * @param int   $sessionId
5049
 * @param bool  $correction
5050
 * @param bool  $forceAccessForCourseAdmins
5051
 *
5052
 * @return array|bool
5053
 */
5054
function getFileContents($id, $courseInfo, $sessionId = 0, $correction = false, $forceAccessForCourseAdmins = false)
5055
{
5056
    $id = (int) $id;
5057
    if (empty($courseInfo) || empty($id)) {
5058
        return false;
5059
    }
5060
    if (empty($sessionId)) {
5061
        $sessionId = api_get_session_id();
5062
    }
5063
5064
    $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5065
    if (!empty($courseInfo['real_id'])) {
5066
        $sql = "SELECT *
5067
                FROM $table
5068
                WHERE c_id = ".$courseInfo['real_id']." AND id = $id";
5069
5070
        $result = Database::query($sql);
5071
        if ($result && Database::num_rows($result)) {
5072
            $row = Database::fetch_array($result, 'ASSOC');
5073
5074
            if ($correction) {
5075
                $row['url'] = $row['url_correction'];
5076
            }
5077
5078
            if (empty($row['url'])) {
5079
                return false;
5080
            }
5081
5082
            $full_file_name = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'.$row['url'];
5083
5084
            $item_info = api_get_item_property_info(
5085
                api_get_course_int_id(),
5086
                'work',
5087
                $row['id'],
5088
                $sessionId
5089
            );
5090
5091
            if (empty($item_info)) {
5092
                return false;
5093
            }
5094
5095
            $isAllow = allowOnlySubscribedUser(
5096
                api_get_user_id(),
5097
                $row['parent_id'],
5098
                $courseInfo['real_id'],
5099
                $forceAccessForCourseAdmins
5100
            );
5101
5102
            if (empty($isAllow)) {
5103
                return false;
5104
            }
5105
5106
            /*
5107
            field show_score in table course :
5108
                0 =>    New documents are visible for all users
5109
                1 =>    New documents are only visible for the teacher(s)
5110
            field visibility in table item_property :
5111
                0 => eye closed, invisible for all students
5112
                1 => eye open
5113
            field accepted in table c_student_publication :
5114
                0 => eye closed, invisible for all students
5115
                1 => eye open
5116
            ( We should have visibility == accepted, otherwise there is an
5117
            inconsistency in the Database)
5118
            field value in table c_course_setting :
5119
                0 => Allow learners to delete their own publications = NO
5120
                1 => Allow learners to delete their own publications = YES
5121
5122
            +------------------+-------------------------+------------------------+
5123
            |Can download work?| doc visible for all = 0 | doc visible for all = 1|
5124
            +------------------+-------------------------+------------------------+
5125
            |  visibility = 0  | editor only             | editor only            |
5126
            |                  |                         |                        |
5127
            +------------------+-------------------------+------------------------+
5128
            |  visibility = 1  | editor                  | editor                 |
5129
            |                  | + owner of the work     | + any student          |
5130
            +------------------+-------------------------+------------------------+
5131
            (editor = teacher + admin + anybody with right api_is_allowed_to_edit)
5132
            */
5133
5134
            $work_is_visible = $item_info['visibility'] == 1 && $row['accepted'] == 1;
5135
            $doc_visible_for_all = (int) $courseInfo['show_score'] === 0;
5136
5137
            $is_editor = api_is_allowed_to_edit(true, true, true);
5138
            $student_is_owner_of_work = user_is_author($row['id'], api_get_user_id());
5139
5140
            if (($forceAccessForCourseAdmins && $isAllow) ||
5141
                $is_editor ||
5142
                $student_is_owner_of_work ||
5143
                ($doc_visible_for_all && $work_is_visible)
5144
            ) {
5145
                $title = $row['title'];
5146
                if ($correction) {
5147
                    $title = $row['title_correction'];
5148
                }
5149
                if (array_key_exists('filename', $row) && !empty($row['filename'])) {
5150
                    $title = $row['filename'];
5151
                }
5152
5153
                $title = str_replace(' ', '_', $title);
5154
5155
                if ($correction == false) {
5156
                    $userInfo = api_get_user_info($row['user_id']);
5157
                    if ($userInfo) {
5158
                        $date = api_get_local_time($row['sent_date']);
5159
                        $date = str_replace([':', '-', ' '], '_', $date);
5160
                        $title = $date.'_'.$userInfo['username'].'_'.$title;
5161
                    }
5162
                }
5163
5164
                if (Security::check_abs_path(
5165
                    $full_file_name,
5166
                    api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'
5167
                )) {
5168
                    Event::event_download($title);
5169
5170
                    return [
5171
                        'path' => $full_file_name,
5172
                        'title' => $title,
5173
                        'title_correction' => $row['title_correction'],
5174
                    ];
5175
                }
5176
            }
5177
        }
5178
    }
5179
5180
    return false;
5181
}
5182
5183
/**
5184
 * @param int    $userId
5185
 * @param array  $courseInfo
5186
 * @param string $format
5187
 *
5188
 * @return bool
5189
 */
5190
function exportAllWork($userId, $courseInfo, $format = 'pdf')
5191
{
5192
    $userInfo = api_get_user_info($userId);
5193
    if (empty($userInfo) || empty($courseInfo)) {
5194
        return false;
5195
    }
5196
5197
    $workPerUser = getWorkPerUser($userId);
5198
5199
    switch ($format) {
5200
        case 'pdf':
5201
            if (!empty($workPerUser)) {
5202
                $pdf = new PDF();
5203
5204
                $content = null;
5205
                foreach ($workPerUser as $work) {
5206
                    $work = $work['work'];
5207
                    foreach ($work->user_results as $userResult) {
5208
                        $content .= $userResult['title'];
5209
                        // No need to use api_get_local_time()
5210
                        $content .= $userResult['sent_date'];
5211
                        $content .= $userResult['qualification'];
5212
                        $content .= $userResult['description'];
5213
                    }
5214
                }
5215
5216
                if (!empty($content)) {
5217
                    $pdf->content_to_pdf(
5218
                        $content,
5219
                        null,
5220
                        api_replace_dangerous_char($userInfo['complete_name']),
5221
                        $courseInfo['code']
5222
                    );
5223
                }
5224
            }
5225
            break;
5226
    }
5227
}
5228
5229
/**
5230
 * @param int    $workId
5231
 * @param array  $courseInfo
5232
 * @param int    $sessionId
5233
 * @param string $format
5234
 *
5235
 * @return bool
5236
 */
5237
function exportAllStudentWorkFromPublication(
5238
    $workId,
5239
    $courseInfo,
5240
    $sessionId,
5241
    $format = 'pdf'
5242
) {
5243
    if (empty($courseInfo)) {
5244
        return false;
5245
    }
5246
5247
    $workData = get_work_data_by_id($workId);
5248
    if (empty($workData)) {
5249
        return false;
5250
    }
5251
5252
    $assignment = get_work_assignment_by_id($workId);
5253
5254
    $courseCode = $courseInfo['code'];
5255
    $header = get_lang('Course').': '.$courseInfo['title'];
5256
    $teachers = CourseManager::getTeacherListFromCourseCodeToString(
5257
        $courseCode
5258
    );
5259
5260
    if (!empty($sessionId)) {
5261
        $sessionInfo = api_get_session_info($sessionId);
5262
        if (!empty($sessionInfo)) {
5263
            $header .= ' - '.$sessionInfo['name'];
5264
            $header .= '<br />'.$sessionInfo['description'];
5265
            $teachers = SessionManager::getCoachesByCourseSessionToString(
5266
                $sessionId,
5267
                $courseInfo['real_id']
5268
            );
5269
        }
5270
    }
5271
5272
    $header .= '<br />'.get_lang('Teachers').': '.$teachers.'<br />';
5273
    $header .= '<br />'.get_lang('Date').': '.api_get_local_time().'<br />';
5274
    $header .= '<br />'.get_lang('WorkName').': '.$workData['title'].'<br />';
5275
5276
    $content = null;
5277
    $expiresOn = null;
5278
5279
    if (!empty($assignment) && isset($assignment['expires_on'])) {
5280
        $content .= '<br /><strong>'.get_lang('PostedExpirationDate').'</strong>: '.api_get_local_time($assignment['expires_on']);
5281
        $expiresOn = api_get_local_time($assignment['expires_on']);
5282
    }
5283
5284
    if (!empty($workData['description'])) {
5285
        $content .= '<br /><strong>'.get_lang('Description').'</strong>: '.$workData['description'];
5286
    }
5287
5288
    $workList = get_work_user_list(null, null, null, null, $workId);
5289
5290
    switch ($format) {
5291
        case 'pdf':
5292
            if (!empty($workList)) {
5293
                $table = new HTML_Table(['class' => 'data_table']);
5294
                $headers = [
5295
                    get_lang('Name'),
5296
                    get_lang('User'),
5297
                    get_lang('HandOutDateLimit'),
5298
                    get_lang('SentDate'),
5299
                    get_lang('FileName'),
5300
                    get_lang('Score'),
5301
                    get_lang('Feedback'),
5302
                ];
5303
5304
                $column = 0;
5305
                foreach ($headers as $header) {
5306
                    $table->setHeaderContents(0, $column, $header);
5307
                    $column++;
5308
                }
5309
5310
                $row = 1;
5311
5312
                //$pdf->set_custom_header($header);
5313
                foreach ($workList as $work) {
5314
                    $content .= '<hr />';
5315
                    // getWorkComments need c_id
5316
                    $work['c_id'] = $courseInfo['real_id'];
5317
5318
                    //$content .= get_lang('Date').': '.api_get_local_time($work['sent_date_from_db']).'<br />';
5319
                    $score = null;
5320
                    if (!empty($work['qualification_only'])) {
5321
                        $score = $work['qualification_only'];
5322
                    }
5323
5324
                    $comments = getWorkComments($work);
5325
5326
                    $feedback = null;
5327
                    if (!empty($comments)) {
5328
                        $content .= '<h4>'.get_lang('Feedback').': </h4>';
5329
                        foreach ($comments as $comment) {
5330
                            $feedback .= get_lang('User').': '.$comment['complete_name'].
5331
                                '<br />';
5332
                            $feedback .= $comment['comment'].'<br />';
5333
                        }
5334
                    }
5335
                    $table->setCellContents($row, 0, strip_tags($workData['title']));
5336
                    $table->setCellContents($row, 1, strip_tags($work['fullname']));
5337
                    $table->setCellContents($row, 2, $expiresOn);
5338
                    $table->setCellContents($row, 3, api_get_local_time($work['sent_date_from_db']));
5339
                    $table->setCellContents($row, 4, strip_tags($work['title']));
5340
                    $table->setCellContents($row, 5, $score);
5341
                    $table->setCellContents($row, 6, $feedback);
5342
5343
                    $row++;
5344
                }
5345
5346
                $content = $table->toHtml();
5347
5348
                if (!empty($content)) {
5349
                    $params = [
5350
                        'filename' => $workData['title'].'_'.api_get_local_time(),
5351
                        'pdf_title' => api_replace_dangerous_char($workData['title']),
5352
                        'course_code' => $courseInfo['code'],
5353
                    ];
5354
                    $pdf = new PDF('A4', null, $params);
5355
                    $pdf->html_to_pdf_with_template($content);
5356
                }
5357
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
5358
            }
5359
            break;
5360
    }
5361
}
5362
5363
/**
5364
 * Downloads all user files per user.
5365
 *
5366
 * @param int   $userId
5367
 * @param array $courseInfo
5368
 *
5369
 * @return bool
5370
 */
5371
function downloadAllFilesPerUser($userId, $courseInfo)
5372
{
5373
    $userInfo = api_get_user_info($userId);
5374
5375
    if (empty($userInfo) || empty($courseInfo)) {
5376
        return false;
5377
    }
5378
5379
    $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
5380
    $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/';
5381
    $zip = new PclZip($tempZipFile);
5382
    $workPerUser = getWorkPerUser($userId);
5383
5384
    if (!empty($workPerUser)) {
5385
        $files = [];
5386
        foreach ($workPerUser as $work) {
5387
            $work = $work['work'];
5388
            foreach ($work->user_results as $userResult) {
5389
                if (empty($userResult['url']) || empty($userResult['contains_file'])) {
5390
                    continue;
5391
                }
5392
                $data = getFileContents($userResult['id'], $courseInfo);
5393
                if (!empty($data) && isset($data['path'])) {
5394
                    $files[basename($data['path'])] = [
5395
                        'title' => $data['title'],
5396
                        'path' => $data['path'],
5397
                    ];
5398
                }
5399
            }
5400
        }
5401
5402
        if (!empty($files)) {
5403
            Session::write('files', $files);
5404
            foreach ($files as $data) {
5405
                $zip->add(
5406
                    $data['path'],
5407
                    PCLZIP_OPT_REMOVE_PATH,
5408
                    $coursePath,
5409
                    PCLZIP_CB_PRE_ADD,
5410
                    'preAddAllWorkStudentCallback'
5411
                );
5412
            }
5413
        }
5414
5415
        // Start download of created file
5416
        $name = basename(api_replace_dangerous_char($userInfo['complete_name'])).'.zip';
5417
        Event::event_download($name.'.zip (folder)');
5418
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
5419
            DocumentManager::file_send_for_download($tempZipFile, true, $name);
5420
            @unlink($tempZipFile);
5421
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
5422
        }
5423
    }
5424
    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
5425
}
5426
5427
/**
5428
 * @param $p_event
5429
 * @param array $p_header
5430
 *
5431
 * @return int
5432
 */
5433
function preAddAllWorkStudentCallback($p_event, &$p_header)
5434
{
5435
    $files = Session::read('files');
5436
    if (isset($files[basename($p_header['stored_filename'])])) {
5437
        $p_header['stored_filename'] = $files[basename($p_header['stored_filename'])]['title'];
5438
5439
        return 1;
5440
    }
5441
5442
    return 0;
5443
}
5444
5445
/**
5446
 * Get all work created by a user.
5447
 *
5448
 * @param int $user_id
5449
 * @param int $courseId
5450
 * @param int $sessionId
5451
 *
5452
 * @return array
5453
 */
5454
function getWorkCreatedByUser($user_id, $courseId, $sessionId)
5455
{
5456
    $items = api_get_item_property_list_by_tool_by_user(
5457
        $user_id,
5458
        'work',
5459
        $courseId,
5460
        $sessionId
5461
    );
5462
5463
    $list = [];
5464
    if (!empty($items)) {
5465
        foreach ($items as $work) {
5466
            $item = get_work_data_by_id(
5467
                $work['ref'],
5468
                $courseId,
5469
                $sessionId
5470
            );
5471
            if (!empty($item)) {
5472
                $list[] = [
5473
                    $item['title'],
5474
                    api_get_local_time($work['insert_date']),
5475
                    api_get_local_time($work['lastedit_date']),
5476
                ];
5477
            }
5478
        }
5479
    }
5480
5481
    return $list;
5482
}
5483
5484
/**
5485
 * @param array $courseInfo
5486
 * @param int   $workId
5487
 *
5488
 * @return bool
5489
 */
5490
function protectWork($courseInfo, $workId)
5491
{
5492
    $userId = api_get_user_id();
5493
    $groupId = api_get_group_id();
5494
    $sessionId = api_get_session_id();
5495
    $workData = get_work_data_by_id($workId);
5496
5497
    if (empty($workData) || empty($courseInfo)) {
5498
        api_not_allowed(true);
5499
    }
5500
5501
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
5502
        return true;
5503
    }
5504
5505
    $workId = $workData['id'];
5506
5507
    if ($workData['active'] != 1) {
5508
        api_not_allowed(true);
5509
    }
5510
5511
    $visibility = api_get_item_visibility($courseInfo, 'work', $workId, $sessionId);
5512
5513
    if ($visibility != 1) {
5514
        api_not_allowed(true);
5515
    }
5516
5517
    $isAllow = allowOnlySubscribedUser($userId, $workId, $courseInfo['real_id']);
5518
    if (empty($isAllow)) {
5519
        api_not_allowed(true);
5520
    }
5521
5522
    $groupInfo = GroupManager::get_group_properties($groupId);
5523
5524
    if (!empty($groupId)) {
5525
        $showWork = GroupManager::user_has_access(
5526
            $userId,
5527
            $groupInfo['iid'],
5528
            GroupManager::GROUP_TOOL_WORK
5529
        );
5530
        if (!$showWork) {
5531
            api_not_allowed(true);
5532
        }
5533
    }
5534
}
5535
5536
/**
5537
 * @param array $courseInfo
5538
 * @param array $work
5539
 */
5540
function deleteCorrection($courseInfo, $work)
5541
{
5542
    if (isset($work['url_correction']) && !empty($work['url_correction']) && isset($work['iid'])) {
5543
        $id = $work['iid'];
5544
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5545
        $sql = "UPDATE $table SET
5546
                    url_correction = '',
5547
                    title_correction = ''
5548
                WHERE iid = $id";
5549
        Database::query($sql);
5550
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
5551
        if (file_exists($coursePath.$work['url_correction'])) {
5552
            if (Security::check_abs_path($coursePath.$work['url_correction'], $coursePath)) {
5553
                unlink($coursePath.$work['url_correction']);
5554
            }
5555
        }
5556
    }
5557
}
5558
5559
/**
5560
 * @param int $workId
5561
 *
5562
 * @return string
5563
 */
5564
function workGetExtraFieldData($workId)
5565
{
5566
    $sessionField = new ExtraField('work');
5567
    $extraFieldData = $sessionField->getDataAndFormattedValues($workId);
5568
    $result = '';
5569
    if (!empty($extraFieldData)) {
5570
        $result .= '<div class="well">';
5571
        foreach ($extraFieldData as $data) {
5572
            $result .= $data['text'].': <b>'.$data['value'].'</b>';
5573
        }
5574
        $result .= '</div>';
5575
    }
5576
5577
    return $result;
5578
}
5579