diff --git a/lib/filebrowser/file_info_context_coursecat.php b/lib/filebrowser/file_info_context_coursecat.php index 5b495263b14..7c354bde06f 100644 --- a/lib/filebrowser/file_info_context_coursecat.php +++ b/lib/filebrowser/file_info_context_coursecat.php @@ -97,7 +97,10 @@ class file_info_context_coursecat extends file_info { protected function get_area_coursecat_description($itemid, $filepath, $filename) { global $CFG; - if (!has_capability('moodle/course:update', $this->context)) { + if (!$this->category->visible and !has_capability('moodle/category:viewhiddencategories', $this->context)) { + return null; + } + if (!has_capability('moodle/category:manage', $this->context)) { return null; } diff --git a/lib/filebrowser/file_info_context_system.php b/lib/filebrowser/file_info_context_system.php index 18331a9fb73..27144c05a66 100644 --- a/lib/filebrowser/file_info_context_system.php +++ b/lib/filebrowser/file_info_context_system.php @@ -145,10 +145,11 @@ class file_info_context_system extends file_info { * @return array of file_info instances */ public function get_children() { - global $DB, $USER; + global $DB; $children = array(); + // Add course categories on the top level that are either visible or user is able to view hidden categories. $course_cats = $DB->get_records('course_categories', array('parent'=>0), 'sortorder', 'id,visible'); foreach ($course_cats as $category) { $context = context_coursecat::instance($category->id); @@ -160,20 +161,49 @@ class file_info_context_system extends file_info { } } - $courses = $DB->get_records('course', array('category'=>0), 'sortorder', 'id,visible'); - foreach ($courses as $course) { - if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $context)) { - continue; - } - $context = context_course::instance($course->id); - if ($child = $this->browser->get_file_info($context)) { - $children[] = $child; + // Add courses where user is enrolled that are located in hidden course categories because they would not + // be present in the above tree but user may still be able to access files in them. + if ($hiddencontexts = $this->get_inaccessible_coursecat_contexts()) { + $courses = enrol_get_my_courses(); + foreach ($courses as $course) { + $context = context_course::instance($course->id); + $parents = $context->get_parent_context_ids(); + if (array_intersect($hiddencontexts, $parents)) { + // This course has hidden parent category. + if ($child = $this->browser->get_file_info($context)) { + $children[] = $child; + } + } } } return $children; } + /** + * Returns list of course categories contexts that current user can not see + * + * @return array array of course categories contexts ids + */ + protected function get_inaccessible_coursecat_contexts() { + global $DB; + + $sql = context_helper::get_preload_record_columns_sql('ctx'); + $records = $DB->get_records_sql("SELECT ctx.id, $sql + FROM {course_categories} c + JOIN {context} ctx ON c.id = ctx.instanceid AND ctx.contextlevel = ? + WHERE c.visible = ?", [CONTEXT_COURSECAT, 0]); + $hiddencontexts = []; + foreach ($records as $record) { + context_helper::preload_from_record($record); + $context = context::instance_by_id($record->id); + if (!has_capability('moodle/category:viewhiddencategories', $context)) { + $hiddencontexts[] = $record->id; + } + } + return $hiddencontexts; + } + /** * Returns parent file_info instance * diff --git a/lib/filelib.php b/lib/filelib.php index 6bd5a85fe51..e23467ab758 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -4182,6 +4182,14 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) { require_login(); } + // Check if user can view this category. + if (!has_capability('moodle/category:viewhiddencategories', $context)) { + $coursecatvisible = $DB->get_field('course_categories', 'visible', array('id' => $context->instanceid)); + if (!$coursecatvisible) { + send_file_not_found(); + } + } + $filename = array_pop($args); $filepath = $args ? '/'.implode('/', $args).'/' : '/'; if (!$file = $fs->get_file($context->id, 'coursecat', 'description', 0, $filepath, $filename) or $file->is_directory()) {