Permalink
Browse files

Merge branch 'wip-MDL-33857-MOODLE_23_STABLE' of git://github.com/mar…

…inaglancy/moodle into MOODLE_23_STABLE
  • Loading branch information...
2 parents c35fa27 + ed7e6a7 commit 4740c0a64f76d448f40f7c4dda98df8d9f357612 Sam Hemelryk committed Oct 16, 2012
@@ -201,8 +201,13 @@ private function get_file_info_context_course($context, $component, $filearea, $
private function get_file_info_context_module($context, $component, $filearea, $itemid, $filepath, $filename) {
global $COURSE, $DB, $CFG;
+ static $cachedmodules = array();
- if (!$cm = get_coursemodule_from_id('', $context->instanceid)) {
+ if (!array_key_exists($context->instanceid, $cachedmodules)) {
+ $cachedmodules[$context->instanceid] = get_coursemodule_from_id('', $context->instanceid);
+ }
+
+ if (!($cm = $cachedmodules[$context->instanceid])) {
return null;
}
@@ -89,6 +89,116 @@ public function get_params() {
public abstract function get_children();
/**
+ * Builds SQL sub query (WHERE clause) for selecting files with the specified extensions
+ *
+ * If $extensions == '*' (any file), the result is array('', array())
+ * otherwise the result is something like array('AND filename ...', array(...))
+ *
+ * @param string|array $extensions - either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
+ * @param string $prefix prefix for DB table files in the query (empty by default)
+ * @return array of two elements: $sql - sql where clause and $params - array of parameters
+ */
+ protected function build_search_files_sql($extensions, $prefix = null) {
+ global $DB;
+ if (strlen($prefix)) {
+ $prefix = $prefix.'.';
+ } else {
+ $prefix = '';
+ }
+ $sql = '';
+ $params = array();
+ if (is_array($extensions) && !in_array('*', $extensions)) {
+ $likes = array();
+ $cnt = 0;
+ foreach ($extensions as $ext) {
+ $cnt++;
+ $likes[] = $DB->sql_like($prefix.'filename', ':filename'.$cnt, false);
+ $params['filename'.$cnt] = '%'.$ext;
+ }
+ $sql .= ' AND ('.join(' OR ', $likes).')';
+ }
+ return array($sql, $params);
+ }
+
+ /**
+ * Returns list of children which are either files matching the specified extensions
+ * or folders that contain at least one such file.
+ *
+ * It is recommended to overwrite this function so it uses a proper SQL
+ * query and does not create unnecessary file_info objects (might require a lot of time
+ * and memory usage on big sites).
+ *
+ * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
+ * @return array of file_info instances
+ */
+ public function get_non_empty_children($extensions = '*') {
+ $list = $this->get_children();
+ $nonemptylist = array();
+ foreach ($list as $fileinfo) {
+ if ($fileinfo->is_directory()) {
+ if ($fileinfo->count_non_empty_children($extensions)) {
+ $nonemptylist[] = $fileinfo;
+ }
+ } else if ($extensions === '*') {
+ $nonemptylist[] = $fileinfo;
+ } else {
+ $filename = $fileinfo->get_visible_name();
+ $extension = textlib::strtolower(pathinfo($filename, PATHINFO_EXTENSION));
+ if (!empty($extension) && in_array('.'.$extension, $extensions)) {
+ $nonemptylist[] = $fileinfo;
+ }
+ }
+ }
+ return $nonemptylist;
+ }
+
+ /**
+ * Returns the number of children which are either files matching the specified extensions
+ * or folders containing at least one such file.
+ *
+ * We usually don't need the exact number of non empty children if it is >=2 (see param $limit)
+ * This function is used by repository_local to evaluate if the folder is empty. But
+ * it also can be used to check if folder has only one subfolder because in some cases
+ * this subfolder can be skipped.
+ *
+ * It is strongly recommended to overwrite this function so it uses a proper SQL
+ * query and does not create file_info objects (later might require a lot of time
+ * and memory usage on big sites).
+ *
+ * @param string|array $extensions, for example '*' or array('.gif','.jpg')
+ * @param int $limit stop counting after at least $limit non-empty children are found
+ * @return int
+ */
+ public function count_non_empty_children($extensions = '*', $limit = 1) {
+ $list = $this->get_children();
+ $cnt = 0;
+ // first loop through files
+ foreach ($list as $fileinfo) {
+ if (!$fileinfo->is_directory()) {
+ if ($extensions !== '*') {
+ $filename = $fileinfo->get_visible_name();
+ $extension = textlib::strtolower(pathinfo($filename, PATHINFO_EXTENSION));
+ if (empty($extension) || !in_array('.'.$extension, $extensions)) {
+ continue;
+ }
+ }
+ if ((++$cnt) >= $limit) {
+ return $cnt;
+ }
+ }
+ }
+ // now loop through directories
+ foreach ($list as $fileinfo) {
+ if ($fileinfo->is_directory() && $fileinfo->count_non_empty_children($extensions)) {
+ if ((++$cnt) >= $limit) {
+ return $cnt;
+ }
+ }
+ }
+ return $cnt;
+ }
+
+ /**
* Returns parent file_info instance
*
* @return file_info or null for root
@@ -350,49 +350,91 @@ public function is_directory() {
* @return array of file_info instances
*/
public function get_children() {
- $children = array();
+ return $this->get_filtered_children('*', false, true);
+ }
- if ($child = $this->get_area_course_summary(0, '/', '.')) {
- $children[] = $child;
- }
- if ($child = $this->get_area_course_section(null, null, null)) {
- $children[] = $child;
- }
- if ($child = $this->get_area_backup_section(null, null, null)) {
- $children[] = $child;
- }
- if ($child = $this->get_area_backup_course(0, '/', '.')) {
- $children[] = $child;
- }
- if ($child = $this->get_area_backup_automated(0, '/', '.')) {
- $children[] = $child;
- }
- if ($child = $this->get_area_course_legacy(0, '/', '.')) {
- $children[] = $child;
+ /**
+ * Help function to return files matching extensions or their count
+ *
+ * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
+ * @param bool|int $countonly if false returns the children, if an int returns just the
+ * count of children but stops counting when $countonly number of children is reached
+ * @param bool $returnemptyfolders if true returns items that don't have matching files inside
+ * @return array|int array of file_info instances or the count
+ */
+ private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) {
+ $areas = array(
+ array('course', 'summary'),
+ array('course', 'section'),
+ array('backup', 'section'),
+ array('backup', 'course'),
+ array('backup', 'automated'),
+ array('course', 'legacy')
+ );
+ $children = array();
+ foreach ($areas as $area) {
+ if ($child = $this->get_file_info($area[0], $area[1], 0, '/', '.')) {
+ if ($returnemptyfolders || $child->count_non_empty_children($extensions)) {
+ $children[] = $child;
+ if (($countonly !== false) && count($children)>=$countonly) {
+ return $countonly;
+ }
+ }
+ }
}
if (!has_capability('moodle/course:managefiles', $this->context)) {
// 'managefiles' capability is checked in every activity module callback.
// Don't even waste time on retrieving the modules if we can't browse the files anyway
- return $children;
- }
-
- // now list all modules
- $modinfo = get_fast_modinfo($this->course);
- foreach ($modinfo->cms as $cminfo) {
- if (empty($cminfo->uservisible)) {
- continue;
- }
- $modcontext = get_context_instance(CONTEXT_MODULE, $cminfo->id);
- if ($child = $this->browser->get_file_info($modcontext)) {
- $children[] = $child;
+ } else {
+ // now list all modules
+ $modinfo = get_fast_modinfo($this->course);
+ foreach ($modinfo->cms as $cminfo) {
+ if (empty($cminfo->uservisible)) {
+ continue;
+ }
+ $modcontext = context_module::instance($cminfo->id, IGNORE_MISSING);
+ if ($child = $this->browser->get_file_info($modcontext)) {
+ if ($returnemptyfolders || $child->count_non_empty_children($extensions)) {
+ $children[] = $child;
+ if (($countonly !== false) && count($children)>=$countonly) {
+ return $countonly;
+ }
+ }
+ }
}
}
+ if ($countonly !== false) {
+ return count($children);
+ }
return $children;
}
/**
+ * Returns list of children which are either files matching the specified extensions
+ * or folders that contain at least one such file.
+ *
+ * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
+ * @return array of file_info instances
+ */
+ public function get_non_empty_children($extensions = '*') {
+ return $this->get_filtered_children($extensions, false);
+ }
+
+ /**
+ * Returns the number of children which are either files matching the specified extensions
+ * or folders containing at least one such file.
+ *
+ * @param string|array $extensions, for example '*' or array('.gif','.jpg')
+ * @param int $limit stop counting after at least $limit non-empty children are found
+ * @return int
+ */
+ public function count_non_empty_children($extensions = '*', $limit = 1) {
+ return $this->get_filtered_children($extensions, $limit);
+ }
+
+ /**
* Returns parent file_info instance
*
* @todo error checking if get_parent_contextid() returns false
@@ -473,6 +515,37 @@ public function get_children() {
return $result;
}
+
+ /**
+ * Returns list of children which are either files matching the specified extensions
+ * or folders that contain at least one such file.
+ *
+ * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
+ * @return array of file_info instances
+ */
+ public function get_non_empty_children($extensions = '*') {
+ if (!$this->lf->is_directory()) {
+ return array();
+ }
+
+ $result = array();
+ $fs = get_file_storage();
+
+ $storedfiles = $fs->get_directory_files($this->context->id, 'course', 'legacy', 0,
+ $this->lf->get_filepath(), false, true, "filepath, filename");
+ foreach ($storedfiles as $file) {
+ $extension = textlib::strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION));
+ if ($file->is_directory() || $extensions === '*' || (!empty($extension) && in_array('.'.$extension, $extensions))) {
+ $fileinfo = new file_info_area_course_legacy($this->browser, $this->context, $file, $this->urlbase, $this->topvisiblename,
+ $this->itemidused, $this->readaccess, $this->writeaccess, false);
+ if (!$file->is_directory() || $fileinfo->count_non_empty_children($extensions)) {
+ $result[] = $fileinfo;
+ }
+ }
+ }
+
+ return $result;
+ }
}
/**
@@ -579,6 +652,41 @@ public function get_children() {
}
/**
+ * Returns the number of children which are either files matching the specified extensions
+ * or folders containing at least one such file.
+ *
+ * @param string|array $extensions, for example '*' or array('.gif','.jpg')
+ * @param int $limit stop counting after at least $limit non-empty children are found
+ * @return int
+ */
+ public function count_non_empty_children($extensions = '*', $limit = 1) {
+ global $DB;
+ $params1 = array(
+ 'courseid' => $this->course->id,
+ 'contextid' => $this->context->id,
+ 'component' => 'course',
+ 'filearea' => 'section',
+ 'emptyfilename' => '.');
+ $sql1 = "SELECT DISTINCT cs.id FROM {files} f, {course_sections} cs
+ WHERE cs.course = :courseid
+ AND f.contextid = :contextid
+ AND f.component = :component
+ AND f.filearea = :filearea
+ AND f.itemid = cs.id
+ AND f.filename <> :emptyfilename";
+ list($sql2, $params2) = $this->build_search_files_sql($extensions);
+ $rs = $DB->get_recordset_sql($sql1. ' '. $sql2, array_merge($params1, $params2));
+ $cnt = 0;
+ foreach ($rs as $record) {
+ if ((++$cnt) >= $limit) {
+ break;
+ }
+ }
+ $rs->close();
+ return $cnt;
+ }
+
+ /**
* Returns parent file_info instance
*
* @return file_info|null file_info or null for root
@@ -690,6 +798,41 @@ public function get_children() {
}
/**
+ * Returns the number of children which are either files matching the specified extensions
+ * or folders containing at least one such file.
+ *
+ * @param string|array $extensions, for example '*' or array('.gif','.jpg')
+ * @param int $limit stop counting after at least $limit non-empty children are found
+ * @return int
+ */
+ public function count_non_empty_children($extensions = '*', $limit = 1) {
+ global $DB;
+ $params1 = array(
+ 'courseid' => $this->course->id,
+ 'contextid' => $this->context->id,
+ 'component' => 'backup',
+ 'filearea' => 'section',
+ 'emptyfilename' => '.');
+ $sql1 = "SELECT DISTINCT cs.id sectionid FROM {files} f, {course_sections} cs
+ WHERE cs.course = :courseid
+ AND f.contextid = :contextid
+ AND f.component = :component
+ AND f.filearea = :filearea
+ AND f.itemid = cs.id
+ AND f.filename <> :emptyfilename";
+ list($sql2, $params2) = $this->build_search_files_sql($extensions);
+ $rs = $DB->get_recordset_sql($sql1. ' '. $sql2, array_merge($params1, $params2));
+ $cnt = 0;
+ foreach ($rs as $record) {
+ if ((++$cnt) >= $limit) {
+ break;
+ }
+ }
+ $rs->close();
+ return $cnt;
+ }
+
+ /**
* Returns parent file_info instance
*
* @return file_info or null for root
Oops, something went wrong.

0 comments on commit 4740c0a

Please sign in to comment.