PageRenderTime 26ms CodeModel.GetById 2ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/filebrowser/file_info_context_coursecat.php

http://github.com/moodle/moodle
PHP | 301 lines | 155 code | 37 blank | 109 comment | 21 complexity | 3d5b860846bf0466bf6f01ae4c83d13d MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
  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 (!core_course_category::can_view_category($this->category)) {
  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 (!core_course_category::can_view_category($this->category)) {
  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. if (!core_course_category::can_view_category($category)) {
  201. $hiddencats[$id] = $coursecats[$id];
  202. unset($coursecats[$id]);
  203. }
  204. }
  205. return [$coursecats, $hiddencats];
  206. }
  207. /**
  208. * Returns the file info element for a given course or null if course is not accessible
  209. *
  210. * @param stdClass $course may contain context fields for preloading
  211. * @return file_info_context_course|null
  212. */
  213. protected function get_child_course($course) {
  214. context_helper::preload_from_record($course);
  215. $context = context_course::instance($course->id);
  216. $child = new file_info_context_course($this->browser, $context, $course);
  217. return $child->get_file_info(null, null, null, null, null);
  218. }
  219. /**
  220. * Returns the number of children which are either files matching the specified extensions
  221. * or folders containing at least one such file.
  222. *
  223. * @param string|array $extensions, for example '*' or array('.gif','.jpg')
  224. * @param int $limit stop counting after at least $limit non-empty children are found
  225. * @return int
  226. */
  227. public function count_non_empty_children($extensions = '*', $limit = 1) {
  228. $cnt = 0;
  229. if ($child = $this->get_area_coursecat_description(0, '/', '.')) {
  230. $cnt += $child->count_non_empty_children($extensions) ? 1 : 0;
  231. if ($cnt >= $limit) {
  232. return $cnt;
  233. }
  234. }
  235. list($coursecats, $hiddencats) = $this->get_categories();
  236. foreach ($coursecats as $category) {
  237. $context = context_coursecat::instance($category->id);
  238. $child = new file_info_context_coursecat($this->browser, $context, $category);
  239. $cnt += $child->count_non_empty_children($extensions) ? 1 : 0;
  240. if ($cnt >= $limit) {
  241. return $cnt;
  242. }
  243. }
  244. $courses = $this->get_courses($hiddencats);
  245. foreach ($courses as $course) {
  246. if ($child = $this->get_child_course($course)) {
  247. $cnt += $child->count_non_empty_children($extensions) ? 1 : 0;
  248. if ($cnt >= $limit) {
  249. return $cnt;
  250. }
  251. }
  252. }
  253. return $cnt;
  254. }
  255. /**
  256. * Returns parent file_info instance
  257. *
  258. * @return file_info|null fileinfo instance or null for root directory
  259. */
  260. public function get_parent() {
  261. $parent = $this->context->get_parent_context();
  262. return $this->browser->get_file_info($parent);
  263. }
  264. }