Passed
Push — master ( 7b6b24...78c3b4 )
by Julito
24:27 queued 15:59
created

getUniqueStudentAttemptsTotal()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 35
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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