Skip to content

Commit 7e64ea4

Browse files
Documents: Safely attach shared files to multiple courses - refs #6372
1 parent 262c23d commit 7e64ea4

File tree

14 files changed

+1143
-351
lines changed

14 files changed

+1143
-351
lines changed

assets/vue/components/documents/ResourceFileLink.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ export default {
2525
},
2626
computed: {
2727
getDataType() {
28-
if (this.resource.resourceNode.firstResourceFile.image) {
28+
const node = this.resource && this.resource.resourceNode
29+
const file = node && node.firstResourceFile
30+
31+
if (file && file.image) {
2932
return "image"
3033
}
31-
if (this.resource.resourceNode.firstResourceFile.video) {
34+
35+
if (file && file.video) {
3236
return "video"
3337
}
3438

assets/vue/components/documents/ResourceIcon.vue

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
icon="folder-generic"
55
/>
66
<BaseIcon
7-
v-else-if="resourceData.resourceNode.firstResourceFile.image"
7+
v-else-if="isImage(resourceData)"
88
icon="file-image"
99
/>
1010
<BaseIcon
11-
v-else-if="resourceData.resourceNode.firstResourceFile.video"
11+
v-else-if="isVideo(resourceData)"
1212
icon="file-video"
1313
/>
1414
<BaseIcon
15-
v-else-if="resourceData.resourceNode.firstResourceFile.text"
15+
v-else-if="hasTextFlag"
1616
icon="file-text"
1717
/>
1818
<BaseIcon
19-
v-else-if="'application/pdf' === resourceData.resourceNode.firstResourceFile.mimeType"
19+
v-else-if="isPdfFile"
2020
icon="file-pdf"
2121
/>
2222
<BaseIcon
@@ -30,15 +30,33 @@
3030
</template>
3131

3232
<script setup>
33+
import { computed } from "vue"
3334
import BaseIcon from "../basecomponents/BaseIcon.vue"
3435
import { useFileUtils } from "../../composables/fileUtils"
3536
36-
const { isAudio } = useFileUtils()
37+
const { isImage, isVideo, isAudio } = useFileUtils()
3738
38-
defineProps({
39+
const props = defineProps({
3940
resourceData: {
4041
type: Object,
4142
required: true,
4243
},
4344
})
45+
46+
const hasTextFlag = computed(() => {
47+
const file = props.resourceData?.resourceNode?.firstResourceFile
48+
return !!file && !!file.text
49+
})
50+
51+
const isPdfFile = computed(() => {
52+
const file = props.resourceData?.resourceNode?.firstResourceFile
53+
54+
if (!file || !file.mimeType) {
55+
return false
56+
}
57+
58+
const mime = String(file.mimeType).split(";")[0].trim().toLowerCase()
59+
60+
return mime === "application/pdf"
61+
})
4462
</script>

assets/vue/views/documents/DocumentsList.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
>
147147
<template #body="slotProps">
148148
{{
149-
slotProps.data.resourceNode.firstResourceFile
149+
slotProps.data.resourceNode && slotProps.data.resourceNode.firstResourceFile
150150
? prettyBytes(slotProps.data.resourceNode.firstResourceFile.size)
151151
: ""
152152
}}
@@ -654,7 +654,14 @@ const showBackButtonIfNotRootFolder = computed(() => {
654654
})
655655
656656
function goToAddVariation(item) {
657-
const resourceFileId = item.resourceNode.firstResourceFile.id
657+
const firstFile = item.resourceNode?.firstResourceFile
658+
if (!firstFile) {
659+
console.warn("Missing firstResourceFile for document", item.iid)
660+
return
661+
}
662+
663+
const resourceFileId = firstFile.id
664+
658665
router.push({
659666
name: "DocumentsAddVariation",
660667
params: { resourceFileId, node: route.params.node },

public/main/inc/lib/document.lib.php

Lines changed: 36 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
use Chamilo\CoreBundle\Entity\Course;
66
use Chamilo\CoreBundle\Entity\ResourceLink;
77
use Chamilo\CoreBundle\Entity\ResourceNode;
8+
use Chamilo\CoreBundle\Entity\Session;
89
use Chamilo\CoreBundle\Enums\ObjectIcon;
910
use Chamilo\CoreBundle\Framework\Container;
1011
use Chamilo\CourseBundle\Entity\CDocument;
12+
use Chamilo\CourseBundle\Entity\CGroup;
1113
use Chamilo\CourseBundle\Repository\CDocumentRepository;
1214
use Doctrine\ORM\EntityManagerInterface;
1315

@@ -541,172 +543,51 @@ public static function get_all_document_folders(
541543
return [];
542544
}
543545

544-
$TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
545-
$groupIid = (int) $groupIid;
546-
$courseId = $courseInfo['real_id'];
547546
$sessionId = api_get_session_id();
548547

549-
$folders = [];
550-
$students = CourseManager::get_user_list_from_course_code(
551-
$courseInfo['code'],
552-
api_get_session_id()
553-
);
554-
555-
$conditionList = [];
556-
if (!empty($students)) {
557-
foreach ($students as $studentId => $studentInfo) {
558-
$conditionList[] = '/shared_folder/sf_user_'.$studentInfo['user_id'];
559-
}
548+
/** @var Course|null $course */
549+
$course = api_get_course_entity();
550+
if (!$course instanceof Course) {
551+
return [];
560552
}
561553

562-
$groupCondition = " l.group_id = $groupIid";
563-
if (empty($groupIid)) {
564-
$groupCondition = ' (l.group_id = 0 OR l.group_id IS NULL)';
554+
/** @var Session|null $session */
555+
$session = null;
556+
if (!empty($sessionId)) {
557+
$session = Container::$container
558+
->get('doctrine')
559+
->getRepository(Session::class)
560+
->find($sessionId);
565561
}
566562

567-
$show_users_condition = '';
568-
if ($can_see_invisible) {
569-
$sessionId = $sessionId ?: api_get_session_id();
570-
$condition_session = " AND (l.session_id = '$sessionId' OR (l.session_id = '0' OR l.session_id IS NULL) )";
571-
$condition_session .= self::getSessionFolderFilters($path, $sessionId);
572-
573-
$sql = "SELECT DISTINCT docs.iid, n.path
574-
FROM resource_node AS n
575-
INNER JOIN $TABLE_DOCUMENT AS docs
576-
ON (docs.resource_node_id = n.id)
577-
INNER JOIN resource_link l
578-
ON (l.resource_node_id = n.id)
579-
WHERE
580-
l.c_id = $courseId AND
581-
docs.filetype = 'folder' AND
582-
$groupCondition AND
583-
n.path NOT LIKE '%shared_folder%' AND
584-
l.deleted_at IS NULL
585-
$condition_session ";
586-
587-
if (0 != $groupIid) {
588-
$sql .= " AND n.path NOT LIKE '%shared_folder%' ";
589-
} else {
590-
$sql .= $show_users_condition;
591-
}
592-
593-
$result = Database::query($sql);
594-
if ($result && 0 != Database::num_rows($result)) {
595-
while ($row = Database::fetch_assoc($result)) {
596-
if (self::is_folder_to_avoid($row['path'])) {
597-
continue;
598-
}
599-
600-
if (false !== strpos($row['path'], '/shared_folder/')) {
601-
if (!in_array($row['path'], $conditionList)) {
602-
continue;
603-
}
604-
}
605-
606-
$folders[$row['iid']] = $row['path'];
607-
}
608-
609-
if (!empty($folders)) {
610-
natsort($folders);
611-
}
612-
613-
return $folders;
614-
}
615-
616-
return false;
617-
} else {
618-
// No invisible folders
619-
// Condition for the session
620-
$condition_session = api_get_session_condition(
621-
$sessionId,
622-
true,
623-
false,
624-
'docs.session_id'
625-
);
626-
627-
$visibilityCondition = 'l.visibility = 1';
628-
$fileType = "docs.filetype = 'folder' AND";
629-
if ($getInvisibleList) {
630-
$visibilityCondition = 'l.visibility = 0';
631-
$fileType = '';
632-
}
633-
634-
//get visible folders
635-
$sql = "SELECT DISTINCT docs.id
636-
FROM resource_node AS n
637-
INNER JOIN $TABLE_DOCUMENT AS docs
638-
ON (docs.resource_node_id = n.id)
639-
INNER JOIN resource_link l
640-
ON (l.resource_node_id = n.id)
641-
WHERE
642-
$fileType
643-
$groupCondition AND
644-
$visibilityCondition
645-
$show_users_condition
646-
$condition_session AND
647-
l.c_id = $courseId ";
648-
$result = Database::query($sql);
649-
$visibleFolders = [];
650-
while ($row = Database::fetch_assoc($result)) {
651-
$visibleFolders[$row['id']] = $row['path'];
652-
}
653-
654-
if ($getInvisibleList) {
655-
return $visibleFolders;
656-
}
657-
658-
// get invisible folders
659-
$sql = "SELECT DISTINCT docs.iid, n.path
660-
FROM resource_node AS n
661-
INNER JOIN $TABLE_DOCUMENT AS docs
662-
ON (docs.resource_node_id = n.id)
663-
INNER JOIN resource_link l
664-
ON (l.resource_node_id = n.id)
665-
WHERE
666-
docs.filetype = 'folder' AND
667-
$groupCondition AND
668-
l.visibility IN ('".ResourceLink::VISIBILITY_PENDING."')
669-
$condition_session AND
670-
l.c_id = $courseId ";
671-
$result = Database::query($sql);
672-
$invisibleFolders = [];
673-
while ($row = Database::fetch_assoc($result)) {
674-
//get visible folders in the invisible ones -> they are invisible too
675-
$sql = "SELECT DISTINCT docs.iid, n.path
676-
FROM resource_node AS n
677-
INNER JOIN $TABLE_DOCUMENT AS docs
678-
ON (docs.resource_node_id = n.id)
679-
INNER JOIN resource_link l
680-
ON (l.resource_node_id = n.id)
681-
WHERE
682-
docs.filetype = 'folder' AND
683-
$groupCondition AND
684-
l.deleted_at IS NULL
685-
$condition_session AND
686-
l.c_id = $courseId ";
687-
$folder_in_invisible_result = Database::query($sql);
688-
while ($folders_in_invisible_folder = Database::fetch_assoc($folder_in_invisible_result)) {
689-
$invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
690-
}
691-
}
692-
693-
// If both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
694-
if (is_array($visibleFolders) && is_array($invisibleFolders)) {
695-
$folders = array_diff($visibleFolders, $invisibleFolders);
696-
natsort($folders);
697-
698-
return $folders;
699-
}
563+
/** @var CGroup|null $group */
564+
$group = null;
565+
if (!empty($groupIid)) {
566+
$group = Container::$container
567+
->get('doctrine')
568+
->getRepository(CGroup::class)
569+
->find($groupIid);
570+
}
700571

701-
if (is_array($visibleFolders)) {
702-
natsort($visibleFolders);
572+
/** @var CDocumentRepository $docRepo */
573+
$docRepo = Container::$container->get('doctrine')
574+
->getRepository(CDocument::class);
703575

704-
return $visibleFolders;
705-
}
576+
$folders = $docRepo->getAllFoldersForContext(
577+
$course,
578+
$session,
579+
$group,
580+
(bool) $can_see_invisible,
581+
(bool) $getInvisibleList
582+
);
706583

707-
// no visible folders found
584+
if (empty($folders)) {
585+
// Keep backward compatibility: some legacy callers expect "false"
586+
// when there are no visible folders.
708587
return false;
709588
}
589+
590+
return $folders;
710591
}
711592

712593
/**

0 commit comments

Comments
 (0)