Passed
Push — master ( 5a0940...f02335 )
by Julito
12:50 queued 02:57
created

exportAllStudentWorkFromPublication()   D

Complexity

Conditions 16

Size

Total Lines 119
Code Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 79
nop 4
dl 0
loc 119
rs 4.9115
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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