Passed
Push — master ( 28eb1d...1071d4 )
by Julito
09:33
created

getWorkList()   C

Complexity

Conditions 14
Paths 90

Size

Total Lines 85
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 54
nc 90
nop 5
dl 0
loc 85
rs 6.2666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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