Passed
Push — master ( 1071d4...e4892a )
by Julito
09:00
created

getFileContents()   D

Complexity

Conditions 19
Paths 115

Size

Total Lines 121
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

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

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
5194
        /** @var CStudentPublication $studentPublication */
5195
        $studentPublication = $file['entity'];
5196
5197
    }
5198
5199
    return false;
5200
}
5201
5202
/**
5203
 * Get the file contents for an assigment.
5204
 *
5205
 * @param int   $id
5206
 * @param array $courseInfo
5207
 * @param int   $sessionId
5208
 * @param bool  $correction
5209
 * @param bool  $forceAccessForCourseAdmins
5210
 *
5211
 * @return array|bool
5212
 */
5213
function getFileContents($id, $courseInfo, $sessionId = 0, $correction = false, $forceAccessForCourseAdmins = false)
5214
{
5215
    $id = (int) $id;
5216
5217
    if (empty($courseInfo) || empty($id)) {
5218
        return false;
5219
    }
5220
    if (empty($sessionId)) {
5221
        $sessionId = api_get_session_id();
5222
    }
5223
5224
    $courseEntity = api_get_course_entity($courseInfo['real_id']);
5225
    $sessionEntity = api_get_session_entity($sessionId);
5226
5227
    $repo = Container::getStudentPublicationRepository();
5228
    /** @var CStudentPublication $studentPublication */
5229
    $studentPublication = $repo->find($id);
5230
5231
    if (empty($studentPublication)) {
5232
        return false;
5233
    }
5234
5235
    if ($correction) {
5236
        //$row['url'] = $row['url_correction'];
5237
    }
5238
    $hasFile = $studentPublication->getResourceNode()->hasResourceFile();
5239
    if (!$hasFile) {
5240
        return false;
5241
    }
5242
5243
    /*
5244
    $item_info = api_get_item_property_info(
5245
        api_get_course_int_id(),
5246
        'work',
5247
        $row['id'],
5248
        $sessionId
5249
    );
5250
5251
    if (empty($item_info)) {
5252
        return false;
5253
    }*/
5254
5255
    $isAllow = allowOnlySubscribedUser(
5256
        api_get_user_id(),
5257
        $studentPublication->getParentId(),
5258
        $courseInfo['real_id'],
5259
        $forceAccessForCourseAdmins
5260
    );
5261
5262
    if (empty($isAllow)) {
5263
        return false;
5264
    }
5265
5266
    /*
5267
    field show_score in table course :
5268
        0 =>    New documents are visible for all users
5269
        1 =>    New documents are only visible for the teacher(s)
5270
    field visibility in table item_property :
5271
        0 => eye closed, invisible for all students
5272
        1 => eye open
5273
    field accepted in table c_student_publication :
5274
        0 => eye closed, invisible for all students
5275
        1 => eye open
5276
    ( We should have visibility == accepted, otherwise there is an
5277
    inconsistency in the Database)
5278
    field value in table c_course_setting :
5279
        0 => Allow learners to delete their own publications = NO
5280
        1 => Allow learners to delete their own publications = YES
5281
5282
    +------------------+-------------------------+------------------------+
5283
    |Can download work?| doc visible for all = 0 | doc visible for all = 1|
5284
    +------------------+-------------------------+------------------------+
5285
    |  visibility = 0  | editor only             | editor only            |
5286
    |                  |                         |                        |
5287
    +------------------+-------------------------+------------------------+
5288
    |  visibility = 1  | editor                  | editor                 |
5289
    |                  | + owner of the work     | + any student          |
5290
    +------------------+-------------------------+------------------------+
5291
    (editor = teacher + admin + anybody with right api_is_allowed_to_edit)
5292
    */
5293
5294
    $work_is_visible = $studentPublication->isVisible($courseEntity, $sessionEntity) && $studentPublication->getAccepted();
5295
    $doc_visible_for_all = 0 === (int) $courseInfo['show_score'];
5296
5297
    $is_editor = api_is_allowed_to_edit(true, true, true);
5298
    $student_is_owner_of_work = user_is_author($studentPublication->getIid(), api_get_user_id());
5299
5300
    if (($forceAccessForCourseAdmins && $isAllow) ||
5301
        $is_editor ||
5302
        $student_is_owner_of_work ||
5303
        ($doc_visible_for_all && $work_is_visible)
5304
    ) {
5305
        $title = $studentPublication->getTitle();
5306
        if ($correction) {
5307
            $title = $studentPublication->getTitleCorrection();
5308
        }
5309
        if ($hasFile) {
5310
            $title = $studentPublication->getResourceNode()->getResourceFile()->getName();
5311
        }
5312
5313
        $title = str_replace(' ', '_', $title);
5314
5315
        if (false == $correction) {
5316
            $userInfo = api_get_user_info($studentPublication->getUserId());
5317
            if ($userInfo) {
5318
                $date = api_get_local_time($studentPublication->getSentDate()->format('Y-m-d H:i:s'));
5319
                $date = str_replace([':', '-', ' '], '_', $date);
5320
                $title = $date.'_'.$userInfo['username'].'_'.$title;
5321
            }
5322
        }
5323
5324
        return [
5325
            //'path' => $full_file_name,
5326
            'title' => $title,
5327
            'title_correction' => $studentPublication->getTitleCorrection(),
5328
            'entity' => $studentPublication,
5329
        ];
5330
5331
    }
5332
5333
    return false;
5334
}
5335
5336
/**
5337
 * @param int    $userId
5338
 * @param array  $courseInfo
5339
 * @param string $format
5340
 *
5341
 * @return bool
5342
 */
5343
function exportAllWork($userId, $courseInfo, $format = 'pdf')
5344
{
5345
    $userInfo = api_get_user_info($userId);
5346
    if (empty($userInfo) || empty($courseInfo)) {
5347
        return false;
5348
    }
5349
5350
    $workPerUser = getWorkPerUser($userId);
5351
5352
    switch ($format) {
5353
        case 'pdf':
5354
            if (!empty($workPerUser)) {
5355
                $pdf = new PDF();
5356
5357
                $content = null;
5358
                foreach ($workPerUser as $work) {
5359
                    $work = $work['work'];
5360
                    foreach ($work->user_results as $userResult) {
5361
                        $content .= $userResult['title'];
5362
                        // No need to use api_get_local_time()
5363
                        $content .= $userResult['sent_date'];
5364
                        $content .= $userResult['qualification'];
5365
                        $content .= $userResult['description'];
5366
                    }
5367
                }
5368
5369
                if (!empty($content)) {
5370
                    $pdf->content_to_pdf(
5371
                        $content,
5372
                        null,
5373
                        api_replace_dangerous_char($userInfo['complete_name']),
5374
                        $courseInfo['code']
5375
                    );
5376
                }
5377
            }
5378
5379
            break;
5380
    }
5381
}
5382
5383
/**
5384
 * @param int    $workId
5385
 * @param array  $courseInfo
5386
 * @param int    $sessionId
5387
 * @param string $format
5388
 *
5389
 * @return bool
5390
 */
5391
function exportAllStudentWorkFromPublication(
5392
    $workId,
5393
    $courseInfo,
5394
    $sessionId,
5395
    $format = 'pdf'
5396
) {
5397
    if (empty($courseInfo)) {
5398
        return false;
5399
    }
5400
5401
    $workData = get_work_data_by_id($workId);
5402
    if (empty($workData)) {
5403
        return false;
5404
    }
5405
5406
    $assignment = get_work_assignment_by_id($workId);
5407
5408
    $courseCode = $courseInfo['code'];
5409
    $header = get_lang('Course').': '.$courseInfo['title'];
5410
    $teachers = CourseManager::getTeacherListFromCourseCodeToString(
5411
        $courseCode
5412
    );
5413
5414
    if (!empty($sessionId)) {
5415
        $sessionInfo = api_get_session_info($sessionId);
5416
        if (!empty($sessionInfo)) {
5417
            $header .= ' - '.$sessionInfo['name'];
5418
            $header .= '<br />'.$sessionInfo['description'];
5419
            $teachers = SessionManager::getCoachesByCourseSessionToString(
5420
                $sessionId,
5421
                $courseInfo['real_id']
5422
            );
5423
        }
5424
    }
5425
5426
    $header .= '<br />'.get_lang('Trainers').': '.$teachers.'<br />';
5427
    $header .= '<br />'.get_lang('Date').': '.api_get_local_time().'<br />';
5428
    $header .= '<br />'.get_lang('Assignment name').': '.$workData['title'].'<br />';
5429
5430
    $content = null;
5431
    $expiresOn = null;
5432
5433
    if (!empty($assignment) && isset($assignment['expires_on'])) {
5434
        $content .= '<br /><strong>'.get_lang('Posted deadline for sending the work (Visible to the learner)').'</strong>: '.api_get_local_time($assignment['expires_on']);
5435
        $expiresOn = api_get_local_time($assignment['expires_on']);
5436
    }
5437
5438
    if (!empty($workData['description'])) {
5439
        $content .= '<br /><strong>'.get_lang('Description').'</strong>: '.$workData['description'];
5440
    }
5441
5442
    $workList = get_work_user_list(null, null, null, null, $workId);
5443
5444
    switch ($format) {
5445
        case 'pdf':
5446
            if (!empty($workList)) {
5447
                $table = new HTML_Table(['class' => 'data_table']);
5448
                $headers = [
5449
                    get_lang('Name'),
5450
                    get_lang('User'),
5451
                    get_lang('Deadline'),
5452
                    get_lang('Sent date'),
5453
                    get_lang('Filename'),
5454
                    get_lang('Score'),
5455
                    get_lang('Feedback'),
5456
                ];
5457
5458
                $column = 0;
5459
                foreach ($headers as $header) {
5460
                    $table->setHeaderContents(0, $column, $header);
5461
                    ++$column;
5462
                }
5463
5464
                $row = 1;
5465
5466
                //$pdf->set_custom_header($header);
5467
                foreach ($workList as $work) {
5468
                    $content .= '<hr />';
5469
                    // getWorkComments need c_id
5470
                    $work['c_id'] = $courseInfo['real_id'];
5471
5472
                    //$content .= get_lang('Date').': '.api_get_local_time($work['sent_date_from_db']).'<br />';
5473
                    $score = null;
5474
                    if (!empty($work['qualification_only'])) {
5475
                        $score = $work['qualification_only'];
5476
                    }
5477
5478
                    $comments = getWorkComments($work);
5479
5480
                    $feedback = null;
5481
                    if (!empty($comments)) {
5482
                        $content .= '<h4>'.get_lang('Feedback').': </h4>';
5483
                        foreach ($comments as $comment) {
5484
                            $feedback .= get_lang('User').': '.$comment['complete_name'].
5485
                                '<br />';
5486
                            $feedback .= $comment['comment'].'<br />';
5487
                        }
5488
                    }
5489
                    $table->setCellContents($row, 0, strip_tags($workData['title']));
5490
                    $table->setCellContents($row, 1, strip_tags($work['fullname']));
5491
                    $table->setCellContents($row, 2, $expiresOn);
5492
                    $table->setCellContents($row, 3, api_get_local_time($work['sent_date_from_db']));
5493
                    $table->setCellContents($row, 4, strip_tags($work['title']));
5494
                    $table->setCellContents($row, 5, $score);
5495
                    $table->setCellContents($row, 6, $feedback);
5496
5497
                    ++$row;
5498
                }
5499
5500
                $content = $table->toHtml();
5501
5502
                if (!empty($content)) {
5503
                    $params = [
5504
                        'filename' => $workData['title'].'_'.api_get_local_time(),
5505
                        'pdf_title' => api_replace_dangerous_char($workData['title']),
5506
                        'course_code' => $courseInfo['code'],
5507
                    ];
5508
                    $pdf = new PDF('A4', null, $params);
5509
                    $pdf->html_to_pdf_with_template($content);
5510
                }
5511
                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...
5512
            }
5513
5514
            break;
5515
    }
5516
}
5517
5518
/**
5519
 * Downloads all user files per user.
5520
 *
5521
 * @param int   $userId
5522
 * @param array $courseInfo
5523
 *
5524
 * @return bool
5525
 */
5526
function downloadAllFilesPerUser($userId, $courseInfo)
5527
{
5528
    $userInfo = api_get_user_info($userId);
5529
5530
    if (empty($userInfo) || empty($courseInfo)) {
5531
        return false;
5532
    }
5533
5534
    $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().'.zip';
5535
    $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/work/';
5536
    $zip = new PclZip($tempZipFile);
5537
    $workPerUser = getWorkPerUser($userId);
5538
5539
    if (!empty($workPerUser)) {
5540
        $files = [];
5541
        foreach ($workPerUser as $work) {
5542
            $work = $work['work'];
5543
            foreach ($work->user_results as $userResult) {
5544
                if (empty($userResult['url']) || empty($userResult['contains_file'])) {
5545
                    continue;
5546
                }
5547
                $data = getFileContents($userResult['id'], $courseInfo);
5548
                if (!empty($data) && isset($data['path'])) {
5549
                    $files[basename($data['path'])] = [
5550
                        'title' => $data['title'],
5551
                        'path' => $data['path'],
5552
                    ];
5553
                }
5554
            }
5555
        }
5556
5557
        if (!empty($files)) {
5558
            Session::write('files', $files);
5559
            foreach ($files as $data) {
5560
                $zip->add(
5561
                    $data['path'],
5562
                    PCLZIP_OPT_REMOVE_PATH,
5563
                    $coursePath,
5564
                    PCLZIP_CB_PRE_ADD,
5565
                    'preAddAllWorkStudentCallback'
5566
                );
5567
            }
5568
        }
5569
5570
        // Start download of created file
5571
        $name = basename(api_replace_dangerous_char($userInfo['complete_name'])).'.zip';
5572
        Event::event_download($name.'.zip (folder)');
5573
        if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
5574
            DocumentManager::file_send_for_download($tempZipFile, true, $name);
5575
            @unlink($tempZipFile);
5576
            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...
5577
        }
5578
    }
5579
    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...
5580
}
5581
5582
/**
5583
 * @param $p_event
5584
 * @param array $p_header
5585
 *
5586
 * @return int
5587
 */
5588
function preAddAllWorkStudentCallback($p_event, &$p_header)
5589
{
5590
    $files = Session::read('files');
5591
    if (isset($files[basename($p_header['stored_filename'])])) {
5592
        $p_header['stored_filename'] = $files[basename($p_header['stored_filename'])]['title'];
5593
5594
        return 1;
5595
    }
5596
5597
    return 0;
5598
}
5599
5600
/**
5601
 * Get all work created by a user.
5602
 *
5603
 * @param int $user_id
5604
 * @param int $courseId
5605
 * @param int $sessionId
5606
 *
5607
 * @return array
5608
 */
5609
function getWorkCreatedByUser($user_id, $courseId, $sessionId)
5610
{
5611
    $items = api_get_item_property_list_by_tool_by_user(
5612
        $user_id,
5613
        'work',
5614
        $courseId,
5615
        $sessionId
5616
    );
5617
5618
    $list = [];
5619
    if (!empty($items)) {
5620
        foreach ($items as $work) {
5621
            $item = get_work_data_by_id(
5622
                $work['ref'],
5623
                $courseId,
5624
                $sessionId
5625
            );
5626
            if (!empty($item)) {
5627
                $list[] = [
5628
                    $item['title'],
5629
                    api_get_local_time($work['insert_date']),
5630
                    api_get_local_time($work['lastedit_date']),
5631
                ];
5632
            }
5633
        }
5634
    }
5635
5636
    return $list;
5637
}
5638
5639
/**
5640
 * @param array $courseInfo
5641
 * @param int   $workId
5642
 *
5643
 * @return bool
5644
 */
5645
function protectWork($courseInfo, $workId)
5646
{
5647
    $userId = api_get_user_id();
5648
    $groupId = api_get_group_id();
5649
    $sessionId = api_get_session_id();
5650
    $workData = get_work_data_by_id($workId);
5651
5652
    if (empty($workData) || empty($courseInfo)) {
5653
        api_not_allowed(true);
5654
    }
5655
5656
    if (api_is_platform_admin() || api_is_allowed_to_edit()) {
5657
        return true;
5658
    }
5659
5660
    $workId = $workData['id'];
5661
5662
    if (1 != $workData['active']) {
5663
        api_not_allowed(true);
5664
    }
5665
5666
    /*$visibility = api_get_item_visibility($courseInfo, 'work', $workId, $sessionId);
5667
    if ($visibility != 1) {
5668
        api_not_allowed(true);
5669
    }*/
5670
5671
    $isAllow = allowOnlySubscribedUser($userId, $workId, $courseInfo['real_id']);
5672
    if (empty($isAllow)) {
5673
        api_not_allowed(true);
5674
    }
5675
5676
    $groupInfo = GroupManager::get_group_properties($groupId);
5677
5678
    if (!empty($groupId)) {
5679
        $showWork = GroupManager::user_has_access(
5680
            $userId,
5681
            $groupInfo['iid'],
5682
            GroupManager::GROUP_TOOL_WORK
5683
        );
5684
        if (!$showWork) {
5685
            api_not_allowed(true);
5686
        }
5687
    }
5688
}
5689
5690
/**
5691
 * @param array $courseInfo
5692
 * @param array $work
5693
 */
5694
function deleteCorrection($courseInfo, $work)
5695
{
5696
    if (isset($work['url_correction']) && !empty($work['url_correction']) && isset($work['iid'])) {
5697
        $id = $work['iid'];
5698
        $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
5699
        $sql = "UPDATE $table SET
5700
                    url_correction = '',
5701
                    title_correction = ''
5702
                WHERE iid = $id";
5703
        Database::query($sql);
5704
        $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/';
5705
        if (file_exists($coursePath.$work['url_correction'])) {
5706
            if (Security::check_abs_path($coursePath.$work['url_correction'], $coursePath)) {
5707
                unlink($coursePath.$work['url_correction']);
5708
            }
5709
        }
5710
    }
5711
}
5712
5713
/**
5714
 * @param int $workId
5715
 *
5716
 * @return string
5717
 */
5718
function workGetExtraFieldData($workId)
5719
{
5720
    $sessionField = new ExtraField('work');
5721
    $extraFieldData = $sessionField->getDataAndFormattedValues($workId);
5722
    $result = '';
5723
    if (!empty($extraFieldData)) {
5724
        $result .= '<div class="well">';
5725
        foreach ($extraFieldData as $data) {
5726
            $result .= $data['text'].': <b>'.$data['value'].'</b>';
5727
        }
5728
        $result .= '</div>';
5729
    }
5730
5731
    return $result;
5732
}
5733