Skip to content

Commit

Permalink
MDL-33857 Increase performance of queries for Server files repository…
Browse files Browse the repository at this point in the history
… (small improvements)
  • Loading branch information
marinaglancy committed Oct 10, 2012
1 parent b8de262 commit 43aadf0
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 144 deletions.
39 changes: 22 additions & 17 deletions lib/filebrowser/file_info.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public function get_non_empty_children($extensions = '*') {
$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;
}
Expand All @@ -156,7 +156,7 @@ public function get_non_empty_children($extensions = '*') {
* 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.
Expand All @@ -166,27 +166,32 @@ public function get_non_empty_children($extensions = '*') {
* 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;
}
}
}
Expand Down
59 changes: 35 additions & 24 deletions lib/filebrowser/file_info_context_course.php
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ public function get_children() {
* 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
*/
Expand All @@ -375,8 +376,8 @@ private function get_filtered_children($extensions = '*', $countonly = false, $r
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;
}
}
}
Expand All @@ -396,15 +397,15 @@ private function get_filtered_children($extensions = '*', $countonly = false, $r
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;
Expand All @@ -425,14 +426,12 @@ public function get_non_empty_children($extensions = '*') {
* 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);
}

/**
Expand Down Expand Up @@ -535,7 +534,7 @@ public function get_non_empty_children($extensions = '*') {
$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);
Expand Down Expand Up @@ -656,29 +655,35 @@ 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.
*
* 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,
'contextid' => $this->context->id,
'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
AND f.filearea = :filearea
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;
}

/**
Expand Down Expand Up @@ -796,29 +801,35 @@ 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.
*
* 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,
'contextid' => $this->context->id,
'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
AND f.filearea = :filearea
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;
}

/**
Expand Down
54 changes: 35 additions & 19 deletions lib/filebrowser/file_info_context_coursecat.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,44 +192,60 @@ 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.
*
* 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;
}

/**
Expand Down
20 changes: 9 additions & 11 deletions lib/filebrowser/file_info_context_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ public function get_children() {
* 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
*/
Expand Down Expand Up @@ -303,13 +304,13 @@ private function get_filtered_children($extensions = '*', $countonly = false, $r
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;
Expand All @@ -319,11 +320,10 @@ private function get_filtered_children($extensions = '*', $countonly = false, $r
* 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;
}
Expand All @@ -335,17 +335,15 @@ public function get_non_empty_children($extensions = '*') {
* 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);
}

/**
Expand Down
Loading

0 comments on commit 43aadf0

Please sign in to comment.