/** * Fetches and returns all the children categories and/or grade_items belonging to this category. * By default only returns the immediate children (depth=1), but deeper levels can be requested, * as well as all levels (0). The elements are indexed by sort order. * * @param bool $include_category_items Whether or not to include category grade_items in the children array * @return array Array of child objects (grade_category and grade_item). */ public function get_children($include_category_items = false) { global $DB; // This function must be as fast as possible ;-) // fetch all course grade items and categories into memory - we do not expect hundreds of these in course // we have to limit the number of queries though, because it will be used often in grade reports $cats = $DB->get_records('grade_categories', array('courseid' => $this->courseid)); $items = $DB->get_records('grade_items', array('courseid' => $this->courseid)); // init children array first foreach ($cats as $catid => $cat) { $cats[$catid]->children = array(); } //first attach items to cats and add category sortorder foreach ($items as $item) { if ($item->itemtype == 'course' or $item->itemtype == 'category') { $cats[$item->iteminstance]->sortorder = $item->sortorder; if (!$include_category_items) { continue; } $categoryid = $item->iteminstance; } else { $categoryid = $item->categoryid; if (empty($categoryid)) { debugging('Found a grade item that isnt in a category'); } } // prevent problems with duplicate sortorders in db $sortorder = $item->sortorder; while (array_key_exists($categoryid, $cats) && array_key_exists($sortorder, $cats[$categoryid]->children)) { $sortorder++; } $cats[$categoryid]->children[$sortorder] = $item; } // now find the requested category and connect categories as children $category = false; foreach ($cats as $catid => $cat) { if (empty($cat->parent)) { if ($cat->path !== '/' . $cat->id . '/') { $grade_category = new grade_category($cat, false); $grade_category->path = '/' . $cat->id . '/'; $grade_category->depth = 1; $grade_category->update('system'); return $this->get_children($include_category_items); } } else { if (empty($cat->path) or !preg_match('|/' . $cat->parent . '/' . $cat->id . '/$|', $cat->path)) { //fix paths and depts static $recursioncounter = 0; // prevents infinite recursion $recursioncounter++; if ($recursioncounter < 5) { // fix paths and depths! $grade_category = new grade_category($cat, false); $grade_category->depth = 0; $grade_category->path = null; $grade_category->update('system'); return $this->get_children($include_category_items); } } // prevent problems with duplicate sortorders in db $sortorder = $cat->sortorder; while (array_key_exists($sortorder, $cats[$cat->parent]->children)) { //debugging("$sortorder exists in cat loop"); $sortorder++; } $cats[$cat->parent]->children[$sortorder] =& $cats[$catid]; } if ($catid == $this->id) { $category =& $cats[$catid]; } } unset($items); // not needed unset($cats); // not needed $children_array = grade_category::_get_children_recursion($category); ksort($children_array); return $children_array; }
/** * Test grade category aggregation using the supplied grade objects and aggregation method * @param grade_category $grade_category the category to be tested * @param array $grade_items array of instance of grade_item * @param array $grade_grades array of instances of grade_grade * @param int $aggmethod the aggregation method to apply ie GRADE_AGGREGATE_MEAN * @param string $aggmethodname the name of the aggregation method to apply. Used to display any test failure messages * @param int $correct1 the correct final grade for the category with NO items hidden * @param int $correct2 the correct final grade for the category with the grade at $grade_grades[0] hidden * @return void */ protected function helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, $aggmethod, $aggmethodname, $correct1, $correct2) { global $DB; $grade_category->aggregation = $aggmethod; $grade_category->update(); //check grade_item isnt hidden from a previous test $grade_items[0]->set_hidden(0, true); $this->helper_test_grade_aggregation_result($grade_category, $correct1, 'Testing aggregation method(' . $aggmethodname . ') with no items hidden %s'); //hide the grade item with grade of 2 $grade_items[0]->set_hidden(1, true); $this->helper_test_grade_aggregation_result($grade_category, $correct2, 'Testing aggregation method(' . $aggmethodname . ') with 1 item hidden %s'); }