MDL-33857 Increase performance of queries for Server files repository (small improvem...
authorMarina Glancy <marina@moodle.com>
Thu, 20 Sep 2012 07:47:52 +0000 (15:47 +0800)
committerMarina Glancy <marina@moodle.com>
Wed, 10 Oct 2012 07:21:27 +0000 (15:21 +0800)
12 files changed:
lib/filebrowser/file_info.php
lib/filebrowser/file_info_context_course.php
lib/filebrowser/file_info_context_coursecat.php
lib/filebrowser/file_info_context_module.php
lib/filebrowser/file_info_stored.php
mod/book/locallib.php
mod/data/locallib.php
mod/forum/locallib.php
mod/glossary/locallib.php
mod/imscp/locallib.php
mod/workshop/fileinfolib.php
repository/local/lib.php

index 9ad0364..0900d68 100644 (file)
@@ -143,7 +143,7 @@ abstract class file_info {
                 $nonemptylist[] = $fileinfo;
             } else {
                 $filename = $fileinfo->get_visible_name();
-                $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
+                $extension = textlib::strtolower(pathinfo($filename, PATHINFO_EXTENSION));
                 if (!empty($extension) && in_array('.'.$extension, $extensions)) {
                     $nonemptylist[] = $fileinfo;
                 }
@@ -156,7 +156,7 @@ abstract class file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
+     * 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.
@@ -166,27 +166,32 @@ abstract class file_info {
      * 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 = '*') {
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
         $list = $this->get_children();
         $cnt = 0;
+        // first loop through files
         foreach ($list as $fileinfo) {
-            if ($cnt > 1) {
-                // it only matters if it is 0, 1 or 2+
-                return $cnt;
-            }
-            if ($fileinfo->is_directory()) {
-                if ($fileinfo->count_non_empty_children($extensions)) {
-                    $cnt++;
+            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;
+                    }
                 }
-            } else if ($extensions === '*') {
-                $cnt++;
-            } else {
-                $filename = $fileinfo->get_visible_name();
-                $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
-                if (!empty($extension) && in_array('.'.$extension, $extensions)) {
-                    $cnt++;
+                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;
                 }
             }
         }
index a82adec..0f691d4 100644 (file)
@@ -357,7 +357,8 @@ class file_info_context_course extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -375,8 +376,8 @@ class file_info_context_course extends file_info {
             if ($child = $this->get_file_info($area[0], $area[1], 0, '/', '.')) {
                 if ($returnemptyfolders || $child->count_non_empty_children($extensions)) {
                     $children[] = $child;
-                    if ($countonly && count($children)>1) {
-                        return 2;
+                    if (($countonly !== false) && count($children)>=$countonly) {
+                        return $countonly;
                     }
                 }
             }
@@ -396,15 +397,15 @@ class file_info_context_course extends file_info {
                 if ($child = $this->browser->get_file_info($modcontext)) {
                     if ($returnemptyfolders || $child->count_non_empty_children($extensions)) {
                         $children[] = $child;
-                        if ($countonly && count($children)>1) {
-                            return 2;
+                        if (($countonly !== false) && count($children)>=$countonly) {
+                            return $countonly;
                         }
                     }
                 }
             }
         }
 
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -425,14 +426,12 @@ class file_info_context_course extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
@@ -535,7 +534,7 @@ class file_info_area_course_legacy extends file_info_stored {
         $storedfiles = $fs->get_directory_files($this->context->id, 'course', 'legacy', 0,
                                                 $this->lf->get_filepath(), false, true, "filepath, filename");
         foreach ($storedfiles as $file) {
-            $extension = strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION));
+            $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);
@@ -656,13 +655,11 @@ class file_info_area_course_section extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
         global $DB;
         $params1 = array(
             'courseid' => $this->course->id,
@@ -670,7 +667,7 @@ class file_info_area_course_section extends file_info {
             'component' => 'course',
             'filearea' => 'section',
             'emptyfilename' => '.');
-        $sql1 = "SELECT 1 from {files} f, {course_sections} cs
+        $sql1 = "SELECT DISTINCT cs.id FROM {files} f, {course_sections} cs
             WHERE cs.course = :courseid
             AND f.contextid = :contextid
             AND f.component = :component
@@ -678,7 +675,15 @@ class file_info_area_course_section extends file_info {
             AND f.itemid = cs.id
             AND f.filename <> :emptyfilename";
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
-        return $DB->record_exists_sql($sql1.' '.$sql2, array_merge($params1, $params2)) ? 2 : 0;
+        $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;
     }
 
     /**
@@ -796,13 +801,11 @@ class file_info_area_backup_section extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
         global $DB;
         $params1 = array(
             'courseid' => $this->course->id,
@@ -810,7 +813,7 @@ class file_info_area_backup_section extends file_info {
             'component' => 'backup',
             'filearea' => 'section',
             'emptyfilename' => '.');
-        $sql1 = "SELECT 1 from {files} f, {course_sections} cs
+        $sql1 = "SELECT DISTINCT cs.id sectionid FROM {files} f, {course_sections} cs
             WHERE cs.course = :courseid
             AND f.contextid = :contextid
             AND f.component = :component
@@ -818,7 +821,15 @@ class file_info_area_backup_section extends file_info {
             AND f.itemid = cs.id
             AND f.filename <> :emptyfilename";
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
-        return $DB->record_exists_sql($sql1.' '.$sql2, array_merge($params1, $params2)) ? 2 : 0;
+        $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;
     }
 
     /**
index 15bf718..09e7cb3 100644 (file)
@@ -192,44 +192,60 @@ class file_info_context_coursecat extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
         global $DB;
+        $cnt = 0;
         if (($child = $this->get_area_coursecat_description(0, '/', '.'))
-                && $child->count_non_empty_children($extensions)) {
-            return 2;
+                && $child->count_non_empty_children($extensions) && (++$cnt) >= $limit) {
+            return $cnt;
         }
 
-        $course_cats = $DB->get_records('course_categories', array('parent'=>$this->category->id), 'sortorder', 'id,visible');
-        foreach ($course_cats as $category) {
-            $context = context_coursecat::instance($category->id);
-            if (!$category->visible and !has_capability('moodle/category:viewhiddencategories', $context)) {
+        $rs = $DB->get_recordset_sql('SELECT ctx.id contextid, c.visible
+                FROM {context} ctx, {course} c
+                WHERE ctx.instanceid = c.id
+                AND ctx.contextlevel = :courselevel
+                AND c.category = :categoryid
+                ORDER BY c.visible DESC', // retrieve visible courses first
+                array('categoryid' => $this->category->id, 'courselevel' => CONTEXT_COURSE));
+        foreach ($rs as $record) {
+            $context = context::instance_by_id($record->contextid);
+            if (!$record->visible and !has_capability('moodle/course:viewhiddencourses', $context)) {
                 continue;
             }
             if (($child = $this->browser->get_file_info($context))
-                    && $child->count_non_empty_children($extensions)) {
-                return 2;
+                    && $child->count_non_empty_children($extensions) && (++$cnt) >= $limit) {
+                break;
             }
         }
+        $rs->close();
+        if ($cnt >= $limit) {
+            return $cnt;
+        }
 
-        $courses = $DB->get_records('course', array('category'=>$this->category->id), 'sortorder', 'id,visible');
-        foreach ($courses as $course) {
-            $context = context_course::instance($course->id);
-            if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $context)) {
+        $rs = $DB->get_recordset_sql('SELECT ctx.id contextid, cat.visible
+                FROM {context} ctx, {course_categories} cat
+                WHERE ctx.instanceid = cat.id
+                AND ctx.contextlevel = :catlevel
+                AND cat.parent = :categoryid
+                ORDER BY cat.visible DESC', // retrieve visible categories first
+                array('categoryid' => $this->category->id, 'catlevel' => CONTEXT_COURSECAT));
+        foreach ($rs as $record) {
+            $context = context::instance_by_id($record->contextid);
+            if (!$record->visible and !has_capability('moodle/category:viewhiddencategories', $context)) {
                 continue;
             }
             if (($child = $this->browser->get_file_info($context))
-                    && $child->count_non_empty_children($extensions)) {
-                return 2;
+                    && $child->count_non_empty_children($extensions) && (++$cnt) >= $limit) {
+                break;
             }
         }
+        $rs->close();
 
-        return 0;
+        return $cnt;
     }
 
     /**
index 7010fad..10e91d7 100644 (file)
@@ -268,7 +268,8 @@ class file_info_context_module extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -303,13 +304,13 @@ class file_info_context_module extends file_info {
             if ($child = $this->get_file_info($area[0], $area[1], null, null, null)) {
                 if ($returnemptyfolders || $child->count_non_empty_children($extensions)) {
                     $children[] = $child;
-                    if ($countonly && count($children)>1) {
+                    if ($countonly !== false && count($children) >= $countonly) {
                         break;
                     }
                 }
             }
         }
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -319,11 +320,10 @@ class file_info_context_module extends file_info {
      * 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')
+     * @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 = '*') {
-        global $DB;
         if ($this->nonemptychildren !== null) {
             return $this->nonemptychildren;
         }
@@ -335,17 +335,15 @@ class file_info_context_module extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     *
-     * @param string|array $extensions, for example '*' or array('.gif','.jpg')
+     * @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 = '*') {
-        global $DB;
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
         if ($this->nonemptychildren !== null) {
             return count($this->nonemptychildren);
         }
-        return $this->get_filtered_children($extensions, true);
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index 1c4d2d2..e9caf4c 100644 (file)
@@ -368,7 +368,7 @@ class file_info_stored extends file_info {
         $storedfiles = $fs->get_directory_files($this->context->id, $this->lf->get_component(), $this->lf->get_filearea(), $this->lf->get_itemid(),
                                                 $this->lf->get_filepath(), false, true, "filepath, filename");
         foreach ($storedfiles as $file) {
-            $extension = strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION));
+            $extension = textlib::strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION));
             if ($file->is_directory() || $extensions === '*' || (!empty($extension) && in_array('.'.$extension, $extensions))) {
                 $fileinfo = new file_info_stored($this->browser, $this->context, $file, $this->urlbase, $this->topvisiblename,
                                                  $this->itemidused, $this->readaccess, $this->writeaccess, false);
@@ -385,13 +385,11 @@ class file_info_stored extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
         global $DB;
         if (!$this->lf->is_directory()) {
             return 0;
@@ -399,7 +397,7 @@ class file_info_stored extends file_info {
 
         $filepath = $this->lf->get_filepath();
         $length = textlib::strlen($filepath);
-        $sql = "SELECT 1
+        $sql = "SELECT filepath, filename
                   FROM {files} f
                  WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea AND f.itemid = :itemid
                        AND ".$DB->sql_substr("f.filepath", 1, $length)." = :filepath
@@ -410,8 +408,24 @@ class file_info_stored extends file_info {
             'itemid' => $this->lf->get_itemid(),
             'filepath' => $filepath);
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
-        // we don't need to check access to individual files here, since the user can access parent
-        return $DB->record_exists_sql($sql.' '.$sql2, array_merge($params, $params2)) ? 2 : 0;
+        $rs = $DB->get_recordset_sql($sql.' '.$sql2, array_merge($params, $params2));
+        $children = array();
+        foreach ($rs as $record) {
+            // we don't need to check access to individual files here, since the user can access parent
+            if ($record->filepath === $filepath) {
+                $children[] = $record->filename;
+            } else {
+                $path = explode('/', textlib::substr($record->filepath, $length));
+                if (!in_array($path[0], $children)) {
+                    $children[] = $path[0];
+                }
+            }
+            if (count($children) >= $limit) {
+                break;
+            }
+        }
+        $rs->close();
+        return count($children);
     }
 
     /**
index eba2e52..9502805 100644 (file)
@@ -455,7 +455,8 @@ class book_file_info extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -479,7 +480,7 @@ class book_file_info extends file_info {
         list($sql2, $params2) = $this->build_search_files_sql($extensions, 'f');
         $sql .= ' '.$sql2;
         $params = array_merge($params, $params2);
-        if (!$countonly) {
+        if ($countonly === false) {
             $sql .= ' ORDER BY bc.pagenum';
         }
 
@@ -491,12 +492,12 @@ class book_file_info extends file_info {
                     $children[] = $child;
                 }
             }
-            if ($countonly && count($children)>1) {
+            if ($countonly !== false && count($children) >= $countonly) {
                 break;
             }
         }
         $rs->close();
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -517,14 +518,12 @@ class book_file_info extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index 280a237..30dbcf6 100644 (file)
@@ -499,7 +499,8 @@ class data_file_info_container extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -520,7 +521,7 @@ class data_file_info_container extends file_info {
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
         $sql .= ' '.$sql2;
         $params = array_merge($params, $params2);
-        if (!$countonly) {
+        if ($countonly === false) {
             $sql .= ' ORDER BY itemid DESC';
         }
 
@@ -530,12 +531,12 @@ class data_file_info_container extends file_info {
             if ($child = $this->browser->get_file_info($this->context, 'mod_data', $this->filearea, $record->itemid)) {
                 $children[] = $child;
             }
-            if ($countonly && count($children)>1) {
+            if ($countonly !== false && count($children) >= $countonly) {
                 break;
             }
         }
         $rs->close();
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -556,14 +557,12 @@ class data_file_info_container extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index f9d6616..c7713f3 100644 (file)
@@ -490,7 +490,8 @@ class forum_file_info_container extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -511,7 +512,7 @@ class forum_file_info_container extends file_info {
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
         $sql .= ' '.$sql2;
         $params = array_merge($params, $params2);
-        if (!$countonly) {
+        if ($countonly !== false) {
             $sql .= ' ORDER BY itemid DESC';
         }
 
@@ -522,12 +523,12 @@ class forum_file_info_container extends file_info {
                     && ($returnemptyfolders || $child->count_non_empty_children($extensions))) {
                 $children[] = $child;
             }
-            if ($countonly && count($children)>1) {
+            if ($countonly !== false && count($children) >= $countonly) {
                 break;
             }
         }
         $rs->close();
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -548,14 +549,12 @@ class forum_file_info_container extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index fdd211f..4a38f39 100644 (file)
@@ -553,7 +553,8 @@ class glossary_file_info_container extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -581,7 +582,7 @@ class glossary_file_info_container extends file_info {
         list($sql2, $params2) = $this->build_search_files_sql($extensions, 'f');
         $sql .= ' '.$sql2;
         $params = array_merge($params, $params2);
-        if (!$countonly) {
+        if ($countonly !== false) {
             $sql .= ' ORDER BY ge.concept, f.itemid';
         }
 
@@ -591,12 +592,12 @@ class glossary_file_info_container extends file_info {
             if ($child = $this->browser->get_file_info($this->context, 'mod_glossary', $this->filearea, $record->itemid)) {
                 $children[] = $child;
             }
-            if ($countonly && count($children)>1) {
+            if ($countonly !== false && count($children) >= $countonly) {
                 break;
             }
         }
         $rs->close();
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -617,14 +618,12 @@ class glossary_file_info_container extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index 169522e..f2755cf 100644 (file)
@@ -280,7 +280,8 @@ class imscp_file_info extends file_info {
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -301,7 +302,7 @@ class imscp_file_info extends file_info {
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
         $sql .= ' '.$sql2;
         $params = array_merge($params, $params2);
-        if (!$countonly) {
+        if ($countonly !== false) {
             $sql .= ' ORDER BY itemid';
         }
 
@@ -310,13 +311,13 @@ class imscp_file_info extends file_info {
         foreach ($rs as $record) {
             if ($child = $this->browser->get_file_info($this->context, 'mod_imscp', $this->filearea, $record->itemid)) {
                 $children[] = $child;
-            }
-            if ($countonly && count($children)>1) {
-                break;
+                if ($countonly !== false && count($children) >= $countonly) {
+                    break;
+                }
             }
         }
         $rs->close();
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -337,14 +338,12 @@ class imscp_file_info extends file_info {
      * Returns the number of children which are either files matching the specified extensions
      * or folders containing at least one such file.
      *
-     * NOTE: We don't need the exact number of non empty children if it is >=2
-     * In this function 1 is never returned to avoid skipping the single subfolder
-     *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index eb1a3bf..35afd24 100644 (file)
@@ -96,11 +96,13 @@ class workshop_file_info_submissions_container extends file_info {
     public function get_children() {
         return $this->get_filtered_children('*', false, true);
     }
+
     /**
      * 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 $countonly if true returns the count of children (0, 1 or 2 if more than 1)
+     * @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
      */
@@ -121,7 +123,7 @@ class workshop_file_info_submissions_container extends file_info {
         list($sql2, $params2) = $this->build_search_files_sql($extensions);
         $sql .= ' '.$sql2;
         $params = array_merge($params, $params2);
-        if (!$countonly) {
+        if ($countonly !== false) {
             $sql .= ' ORDER BY itemid DESC';
         }
 
@@ -131,13 +133,13 @@ class workshop_file_info_submissions_container extends file_info {
             if (($child = $this->browser->get_file_info($this->context, 'mod_workshop', $this->filearea, $record->itemid))
                     && ($returnemptyfolders || $child->count_non_empty_children($extensions))) {
                 $children[] = $child;
-            }
-            if ($countonly && count($children)>1) {
-                break;
+                if ($countonly !== false && count($children) >= $countonly) {
+                    break;
+                }
             }
         }
         $rs->close();
-        if ($countonly) {
+        if ($countonly !== false) {
             return count($children);
         }
         return $children;
@@ -162,10 +164,11 @@ class workshop_file_info_submissions_container extends file_info {
      * In this function 1 is never returned to avoid skipping the single subfolder
      *
      * @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 = '*') {
-        return $this->get_filtered_children($extensions, true);
+    public function count_non_empty_children($extensions = '*', $limit = 1) {
+        return $this->get_filtered_children($extensions, $limit);
     }
 
     /**
index 9e5b743..f3be156 100644 (file)
@@ -67,10 +67,7 @@ class repository_local extends repository {
             }
         }
         if (empty($context) && !empty($this->context)) {
-            list($repositorycontext, $course, $cm) = get_context_info_array($this->context->id);
-            if (isset($course->id)) {
-                $context = context_course::instance($course->id);
-            }
+            $context = $this->context->get_course_context(false);
         }
         if (empty($context)) {
             $context = context_system::instance();
@@ -85,7 +82,7 @@ class repository_local extends repository {
             if (!is_array($extensions)) {
                 $extensions = array($extensions);
             }
-            $extensions = array_map('strtolower', $extensions);
+            $extensions = array_map('textlib::strtolower', $extensions);
         }
 
         // build file tree
@@ -143,7 +140,7 @@ class repository_local extends repository {
     /**
      * Returns all children elements that have one of the specified extensions
      *
-     * This function may skip subfolers and recursively add their children
+     * This function may skip subfolders and recursively add their children
      * {@link repository_local::can_skip()}
      *
      * @param file_info $fileinfo
@@ -164,7 +161,7 @@ class repository_local extends repository {
     }
 
     /**
-     * Wether this folder may be skipped in folder hierarchy
+     * Whether this folder may be skipped in folder hierarchy
      *
      * 1. Skip the name of a single filearea in a module
      * 2. Skip course categories for non-admins who do not have navshowmycoursecategories setting
@@ -176,7 +173,6 @@ class repository_local extends repository {
      */
     private function can_skip(file_info $fileinfo, $extensions, $parent = -1) {
         global $CFG;
-        static $skipcategories = null;
         if (!$fileinfo->is_directory()) {
             // do not skip files
             return false;
@@ -196,13 +192,14 @@ class repository_local extends repository {
             $params = $fileinfo->get_params();
             if (strlen($params['filearea']) &&
                     ($params['filepath'] === '/' || empty($params['filepath'])) &&
-                    ($params['filename'] === '.' || empty($params['filename']))) {
+                    ($params['filename'] === '.' || empty($params['filename'])) &&
+                    context::instance_by_id($params['contextid'])->contextlevel == CONTEXT_MODULE) {
                 if ($parent === -1) {
                     $parent = $fileinfo->get_parent();
                 }
                 // This is a filearea inside an activity, it can be skipped if it has no non-empty siblings
                 if ($parent && ($parent instanceof file_info_context_module)) {
-                    if ($parent->count_non_empty_children($extensions) <= 1) {
+                    if ($parent->count_non_empty_children($extensions, 2) <= 1) {
                         return true;
                     }
                 }