Passed
Push — 1.11.x ( b2716d...f5a86a )
by Julito
21:47
created

sendAlertToUsers()   C

Complexity

Conditions 12
Paths 25

Size

Total Lines 78
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
eloc 49
c 3
b 0
f 0
nc 25
nop 4
dl 0
loc 78
rs 6.9666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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