Completed
Push — master ( 1a5e2c...34133a )
by Julito
08:10
created

getWorkCommentForm()   C

Complexity

Conditions 12
Paths 144

Size

Total Lines 68
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 45
c 1
b 0
f 0
nc 144
nop 2
dl 0
loc 68
rs 6.6

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