From 176b75b59cd60d0bb32573b8bc91b4e57c995529 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Thu, 29 Mar 2012 12:29:40 +1300 Subject: [PATCH] MDL-28967 navigation: Optimised load_all_categories to load preload contexts to greatly reduce database queries --- lib/navigationlib.php | 59 +++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/lib/navigationlib.php b/lib/navigationlib.php index 11d99d42091..7f0c3a48ac9 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -1750,50 +1750,65 @@ class global_navigation extends navigation_node { return true; } + $catcontextsql = context_helper::get_preload_record_columns_sql('ctx'); + $sqlselect = "SELECT cc.*, $catcontextsql + FROM {course_categories} cc + JOIN {context} ctx ON cc.id = ctx.instanceid"; + $sqlwhere = "WHERE ctx.contextlevel = ".CONTEXT_COURSECAT; + $sqlorder = "ORDER BY depth ASC, sortorder ASC, id ASC"; + $params = array(); + $categoriestoload = array(); if ($categoryid == self::LOAD_ALL_CATEGORIES) { - $categories = $DB->get_records('course_categories', null, 'sortorder ASC, id ASC'); + // We are going to load all categories regardless... prepare to fire + // on the database server! } else if ($categoryid == self::LOAD_ROOT_CATEGORIES) { // can be 0 // We are going to load all of the first level categories (categories without parents) - $categories = $DB->get_records('course_categories', array('parent'=>'0'), 'sortorder ASC, id ASC'); + $sqlwhere .= " AND cc.parent = 0"; } else if (array_key_exists($categoryid, $this->addedcategories)) { // The category itself has been loaded already so we just need to ensure its subcategories // have been loaded list($sql, $params) = $DB->get_in_or_equal(array_keys($this->addedcategories), SQL_PARAMS_NAMED, 'parent', false); if ($showbasecategories) { // We need to include categories with parent = 0 as well - $sql = "SELECT * - FROM {course_categories} cc - WHERE (parent = :categoryid OR parent = 0) AND - parent {$sql} - ORDER BY depth DESC, sortorder ASC, id ASC"; + $sqlwhere .= " AND (parent = :categoryid OR parent = 0) AND parent {$sql}"; } else { - $sql = "SELECT * - FROM {course_categories} cc - WHERE parent = :categoryid AND - parent {$sql} - ORDER BY depth DESC, sortorder ASC, id ASC"; + // All we need is categories that match the parent + $sqlwhere .= " AND parent = :categoryid AND parent {$sql}"; } $params['categoryid'] = $categoryid; - $categories = $DB->get_records_sql($sql, $params); - if (count($categories) == 0) { - // There are no further categories that require loading. - return; - } } else { // This category hasn't been loaded yet so we need to fetch it, work out its category path // and load this category plus all its parents and subcategories $category = $DB->get_record('course_categories', array('id' => $categoryid), 'path', MUST_EXIST); $categoriestoload = explode('/', trim($category->path, '/')); list($select, $params) = $DB->get_in_or_equal($categoriestoload); - $select = 'id '.$select.' OR parent '.$select; - if ($showbasecategories) { - $select .= ' OR depth = 1'; - } + // We are going to use select twice so double the params $params = array_merge($params, $params); - $categories = $DB->get_records_select('course_categories', $select, $params, 'sortorder'); + $basecategorysql = ($showbasecategories)?' OR depth = 1':''; + $sqlwhere .= " AND (id {$select} OR parent {$select}{$basecategorysql})"; } + $categoriesrs = $DB->get_recordset_sql("$sqlselect $sqlwhere $sqlorder", $params); + $categories = array(); + foreach ($categoriesrs as $category) { + // Preload the context.. we'll need it when adding the category in order + // to format the category name. + context_helper::preload_from_record($category); + if (array_key_exists($category->id, $this->addedcategories)) { + // Do nothing, its already been added. + } else if ($category->parent == '0') { + // This is a root category lets add it immediately + $this->add_category($category, $this->rootnodes['courses']); + } else if (array_key_exists($category->parent, $this->addedcategories)) { + // This categories parent has already been added we can add this immediately + $this->add_category($category, $this->addedcategories[$category->parent]); + } else { + $categories[] = $category; + } + } + $categoriesrs->close(); + // Now we have an array of categories we need to add them to the navigation. while (!empty($categories)) { $category = reset($categories);