PageRenderTime 46ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/filebrowser/file_info_context_coursecat.php

https://gitlab.com/unofficial-mirrors/moodle
PHP | 302 lines | 156 code | 37 blank | 109 comment | 22 complexity | 00bec5ed2c538b40fabd1bd751d32286 MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Utility class for browsing of curse category files.
  18. *
  19. * @package core_files
  20. * @copyright 2008 Petr Skoda (http://skodak.org)
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. defined('MOODLE_INTERNAL') || die();
  24. /**
  25. * Represents a course category context in the tree navigated by {@link file_browser}.
  26. *
  27. * @package core_files
  28. * @copyright 2008 Petr Skoda (http://skodak.org)
  29. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30. */
  31. class file_info_context_coursecat extends file_info {
  32. /** @var stdClass Category object */
  33. protected $category;
  34. /**
  35. * Constructor
  36. *
  37. * @param file_browser $browser file browser instance
  38. * @param stdClass $context context object
  39. * @param stdClass $category category object
  40. */
  41. public function __construct($browser, $context, $category) {
  42. parent::__construct($browser, $context);
  43. $this->category = $category;
  44. }
  45. /**
  46. * Return information about this specific context level
  47. *
  48. * @param string $component component
  49. * @param string $filearea file area
  50. * @param int $itemid item ID
  51. * @param string $filepath file path
  52. * @param string $filename file name
  53. * @return fileinfo|null
  54. */
  55. public function get_file_info($component, $filearea, $itemid, $filepath, $filename) {
  56. global $DB;
  57. if (!$this->category->visible and !has_capability('moodle/category:viewhiddencategories', $this->context)) {
  58. if (empty($component)) {
  59. // we can not list the category contents, so try parent, or top system
  60. if ($this->category->parent and $pc = $DB->get_record('course_categories', array('id'=>$this->category->parent))) {
  61. $parent = context_coursecat::instance($pc->id, IGNORE_MISSING);
  62. return $this->browser->get_file_info($parent);
  63. } else {
  64. return $this->browser->get_file_info();
  65. }
  66. }
  67. return null;
  68. }
  69. if (empty($component)) {
  70. return $this;
  71. }
  72. $methodname = "get_area_{$component}_{$filearea}";
  73. if (method_exists($this, $methodname)) {
  74. return $this->$methodname($itemid, $filepath, $filename);
  75. }
  76. return null;
  77. }
  78. /**
  79. * Return a file from course category description area
  80. *
  81. * @param int $itemid item ID
  82. * @param string $filepath file path
  83. * @param string $filename file name
  84. * @return fileinfo|null
  85. */
  86. protected function get_area_coursecat_description($itemid, $filepath, $filename) {
  87. global $CFG;
  88. if (!$this->category->id) {
  89. // No coursecat description area for "system".
  90. return null;
  91. }
  92. if (!$this->category->visible and !has_capability('moodle/category:viewhiddencategories', $this->context)) {
  93. return null;
  94. }
  95. if (!has_capability('moodle/category:manage', $this->context)) {
  96. return null;
  97. }
  98. if (is_null($itemid)) {
  99. return $this;
  100. }
  101. $fs = get_file_storage();
  102. $filepath = is_null($filepath) ? '/' : $filepath;
  103. $filename = is_null($filename) ? '.' : $filename;
  104. $urlbase = $CFG->wwwroot.'/pluginfile.php';
  105. if (!$storedfile = $fs->get_file($this->context->id, 'coursecat', 'description', 0, $filepath, $filename)) {
  106. if ($filepath === '/' and $filename === '.') {
  107. $storedfile = new virtual_root_file($this->context->id, 'coursecat', 'description', 0);
  108. } else {
  109. // not found
  110. return null;
  111. }
  112. }
  113. return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('areacategoryintro', 'repository'), false, true, true, false);
  114. }
  115. /**
  116. * Returns localised visible name.
  117. *
  118. * @return string
  119. */
  120. public function get_visible_name() {
  121. return format_string($this->category->name, true, array('context'=>$this->context));
  122. }
  123. /**
  124. * Whether or not new files or directories can be added
  125. *
  126. * @return bool
  127. */
  128. public function is_writable() {
  129. return false;
  130. }
  131. /**
  132. * Whether or not this is a directory
  133. *
  134. * @return bool
  135. */
  136. public function is_directory() {
  137. return true;
  138. }
  139. /**
  140. * Returns list of children.
  141. *
  142. * @return array of file_info instances
  143. */
  144. public function get_children() {
  145. $children = array();
  146. if ($child = $this->get_area_coursecat_description(0, '/', '.')) {
  147. $children[] = $child;
  148. }
  149. list($coursecats, $hiddencats) = $this->get_categories();
  150. foreach ($coursecats as $category) {
  151. $context = context_coursecat::instance($category->id);
  152. $children[] = new self($this->browser, $context, $category);
  153. }
  154. $courses = $this->get_courses($hiddencats);
  155. foreach ($courses as $course) {
  156. $children[] = $this->get_child_course($course);
  157. }
  158. return array_filter($children);
  159. }
  160. /**
  161. * List of courses in this category and in hidden subcategories
  162. *
  163. * @param array $hiddencats list of categories that are hidden from current user and returned by {@link get_categories()}
  164. * @return array list of courses
  165. */
  166. protected function get_courses($hiddencats) {
  167. global $DB, $CFG;
  168. require_once($CFG->libdir.'/modinfolib.php');
  169. $params = array('category' => $this->category->id, 'contextlevel' => CONTEXT_COURSE);
  170. $sql = 'c.category = :category';
  171. foreach ($hiddencats as $category) {
  172. $catcontext = context_coursecat::instance($category->id);
  173. $sql .= ' OR ' . $DB->sql_like('ctx.path', ':path' . $category->id);
  174. $params['path' . $category->id] = $catcontext->path . '/%';
  175. }
  176. // Let's retrieve only minimum number of fields from course table -
  177. // what is needed to check access or call get_fast_modinfo().
  178. $coursefields = array_merge(['id', 'visible'], course_modinfo::$cachedfields);
  179. $fields = 'c.' . join(',c.', $coursefields) . ', ' .
  180. context_helper::get_preload_record_columns_sql('ctx');
  181. return $DB->get_records_sql('SELECT ' . $fields . ' FROM {course} c
  182. JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)
  183. WHERE ('.$sql.') ORDER BY c.sortorder', $params);
  184. }
  185. /**
  186. * Finds accessible and non-accessible direct subcategories
  187. *
  188. * @return array [$coursecats, $hiddencats] - child categories that are visible to the current user and not visible
  189. */
  190. protected function get_categories() {
  191. global $DB;
  192. $fields = 'c.*, ' . context_helper::get_preload_record_columns_sql('ctx');
  193. $coursecats = $DB->get_records_sql('SELECT ' . $fields . ' FROM {course_categories} c
  194. LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)
  195. WHERE c.parent = :parent ORDER BY c.sortorder',
  196. array('parent' => $this->category->id, 'contextlevel' => CONTEXT_COURSECAT));
  197. $hiddencats = [];
  198. foreach ($coursecats as $id => &$category) {
  199. context_helper::preload_from_record($category);
  200. $context = context_coursecat::instance($category->id);
  201. if (!$category->visible && !has_capability('moodle/category:viewhiddencategories', $context)) {
  202. $hiddencats[$id] = $coursecats[$id];
  203. unset($coursecats[$id]);
  204. }
  205. }
  206. return [$coursecats, $hiddencats];
  207. }
  208. /**
  209. * Returns the file info element for a given course or null if course is not accessible
  210. *
  211. * @param stdClass $course may contain context fields for preloading
  212. * @return file_info_context_course|null
  213. */
  214. protected function get_child_course($course) {
  215. context_helper::preload_from_record($course);
  216. $context = context_course::instance($course->id);
  217. $child = new file_info_context_course($this->browser, $context, $course);
  218. return $child->get_file_info(null, null, null, null, null);
  219. }
  220. /**
  221. * Returns the number of children which are either files matching the specified extensions
  222. * or folders containing at least one such file.
  223. *
  224. * @param string|array $extensions, for example '*' or array('.gif','.jpg')
  225. * @param int $limit stop counting after at least $limit non-empty children are found
  226. * @return int
  227. */
  228. public function count_non_empty_children($extensions = '*', $limit = 1) {
  229. $cnt = 0;
  230. if ($child = $this->get_area_coursecat_description(0, '/', '.')) {
  231. $cnt += $child->count_non_empty_children($extensions) ? 1 : 0;
  232. if ($cnt >= $limit) {
  233. return $cnt;
  234. }
  235. }
  236. list($coursecats, $hiddencats) = $this->get_categories();
  237. foreach ($coursecats as $category) {
  238. $context = context_coursecat::instance($category->id);
  239. $child = new file_info_context_coursecat($this->browser, $context, $category);
  240. $cnt += $child->count_non_empty_children($extensions) ? 1 : 0;
  241. if ($cnt >= $limit) {
  242. return $cnt;
  243. }
  244. }
  245. $courses = $this->get_courses($hiddencats);
  246. foreach ($courses as $course) {
  247. if ($child = $this->get_child_course($course)) {
  248. $cnt += $child->count_non_empty_children($extensions) ? 1 : 0;
  249. if ($cnt >= $limit) {
  250. return $cnt;
  251. }
  252. }
  253. }
  254. return $cnt;
  255. }
  256. /**
  257. * Returns parent file_info instance
  258. *
  259. * @return file_info|null fileinfo instance or null for root directory
  260. */
  261. public function get_parent() {
  262. $parent = $this->context->get_parent_context();
  263. return $this->browser->get_file_info($parent);
  264. }
  265. }