function test_grade_category_fetch() { $grade_category = new grade_category(); $this->assertTrue(method_exists($grade_category, 'fetch')); $grade_category = grade_category::fetch(array('id' => $this->grade_categories[0]->id)); $this->assertEqual($this->grade_categories[0]->id, $grade_category->id); $this->assertEqual($this->grade_categories[0]->fullname, $grade_category->fullname); }
/** * Adds a grade category and moves the specified item into it. * Uses locks to prevent race conditions (see MDL-37055). */ public function execute() { $customdata = $this->get_custom_data(); // Get lock timeout. $timeout = 5; // A namespace for the locks. $locktype = 'block_mhaairs_add_category'; // Resource key - course id and category name. $resource = "course: {$customdata->courseid}; catname: {$customdata->catname}"; // Get an instance of the currently configured lock_factory. $lockfactory = \core\lock\lock_config::get_lock_factory($locktype); // Open a lock. $lock = $lockfactory->get_lock($resource, $timeout); // Add the category. $catparams = array('fullname' => $customdata->catname, 'courseid' => $customdata->courseid); if (!($category = \grade_category::fetch($catparams))) { // If the category does not exist we create it. $gradeaggregation = get_config('core', 'grade_aggregation'); if ($gradeaggregation === false) { $gradeaggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; } // Parent category is automatically added(created) during insert. $catparams['hidden'] = false; $catparams['aggregation'] = $gradeaggregation; try { $category = new \grade_category($catparams, false); $category->id = $category->insert(); } catch (Exception $e) { // Must release the locks. $lock->release(); // Rethrow to reschedule task. throw $e; } } // Release locks. $lock->release(); // Add the item to the category. $gitem = \grade_item::fetch(array('id' => $customdata->itemid)); $gitem->categoryid = $category->id; $gitem->update(); }
/** * Recursive function for building the table holding the grade categories and items, * with CSS indentation and styles. * * @param array $element The current tree element being rendered * @param boolean $totals Whether or not to print category grade items (category totals) * @param array $parents An array of parent categories for the current element (used for indentation and row classes) * * @return string HTML */ public function build_html_tree($element, $totals, $parents, $level, &$row_count) { global $CFG, $COURSE, $PAGE, $OUTPUT; $object = $element['object']; $eid = $element['eid']; $object->name = $this->gtree->get_element_header($element, true, true, true, true); $object->stripped_name = $this->gtree->get_element_header($element, false, false, false); $is_category_item = false; if ($element['type'] == 'categoryitem' || $element['type'] == 'courseitem') { $is_category_item = true; } $rowclasses = array(); foreach ($parents as $parent_eid) { $rowclasses[] = $parent_eid; } $moveaction = ''; $actionsmenu = new action_menu(); $actionsmenu->initialise_js($PAGE); $actionsmenu->set_menu_trigger(get_string('edit')); $actionsmenu->set_owner_selector('grade-item-' . $eid); $actionsmenu->set_alignment(action_menu::TL, action_menu::BL); if (!$is_category_item && ($icon = $this->gtree->get_edit_icon($element, $this->gpr, true))) { $actionsmenu->add($icon); } if ($this->show_calculations && ($icon = $this->gtree->get_calculation_icon($element, $this->gpr, true))) { $actionsmenu->add($icon); } if ($element['type'] == 'item' or $element['type'] == 'category' and $element['depth'] > 1) { if ($this->element_deletable($element)) { $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'delete', 'eid' => $eid, 'sesskey' => sesskey())); $icon = new action_menu_link_secondary($aurl, new pix_icon('t/delete', get_string('delete')), get_string('delete')); $actionsmenu->add($icon); } $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'moveselect', 'eid' => $eid, 'sesskey' => sesskey())); $moveaction .= $OUTPUT->action_icon($aurl, new pix_icon('t/move', get_string('move'))); } if ($icon = $this->gtree->get_hiding_icon($element, $this->gpr, true)) { $actionsmenu->add($icon); } if ($icon = $this->gtree->get_reset_icon($element, $this->gpr, true)) { $actionsmenu->add($icon); } $actions = $OUTPUT->render($actionsmenu); $returnrows = array(); $root = false; $id = required_param('id', PARAM_INT); /// prepare move target if needed $last = ''; /// print the list items now if ($this->moving == $eid) { // do not diplay children $cell = new html_table_cell(); $cell->colspan = 12; $cell->attributes['class'] = $element['type'] . ' moving column-name level' . ($level + 1) . ' level' . ($level % 2 ? 'even' : 'odd'); $cell->text = $object->name . ' (' . get_string('move') . ')'; return array(new html_table_row(array($cell))); } if ($element['type'] == 'category') { $level++; $this->categories[$object->id] = $object->stripped_name; $category = grade_category::fetch(array('id' => $object->id)); $item = $category->get_grade_item(); // Add aggregation coef input if not a course item and if parent category has correct aggregation type $dimmed = $item->is_hidden() ? 'dimmed_text' : ''; // Before we print the category's row, we must find out how many rows will appear below it (for the filler cell's rowspan) $aggregation_position = grade_get_setting($COURSE->id, 'aggregationposition', $CFG->grade_aggregationposition); $category_total_data = null; // Used if aggregationposition is set to "last", so we can print it last $html_children = array(); $row_count = 0; foreach ($element['children'] as $child_el) { $moveto = null; if (empty($child_el['object']->itemtype)) { $child_el['object']->itemtype = false; } if (($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') && !$totals) { continue; } $child_eid = $child_el['eid']; $first = ''; if ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') { $first = array('first' => 1); $child_eid = $eid; } if ($this->moving && $this->moving != $child_eid) { $strmove = get_string('move'); $strmovehere = get_string('movehere'); $actions = $moveaction = ''; // no action icons when moving $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'move', 'eid' => $this->moving, 'moveafter' => $child_eid, 'sesskey' => sesskey())); if ($first) { $aurl->params($first); } $cell = new html_table_cell(); $cell->colspan = 12; $cell->attributes['class'] = 'movehere level' . ($level + 1) . ' level' . ($level % 2 ? 'even' : 'odd'); $icon = new pix_icon('movehere', $strmovehere, null, array('class' => 'movetarget')); $cell->text = $OUTPUT->action_icon($aurl, $icon); $moveto = new html_table_row(array($cell)); } $newparents = $parents; $newparents[] = $eid; $row_count++; $child_row_count = 0; // If moving, do not print course and category totals, but still print the moveto target box if ($this->moving && ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category')) { $html_children[] = $moveto; } elseif ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') { // We don't build the item yet because we first need to know the deepest level of categories (for category/name colspans) $category_total_item = $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count); if (!$aggregation_position) { $html_children = array_merge($html_children, $category_total_item); } } else { $html_children = array_merge($html_children, $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count)); if (!empty($moveto)) { $html_children[] = $moveto; } if ($this->moving) { $row_count++; } } $row_count += $child_row_count; // If the child is a category, increment row_count by one more (for the extra coloured row) if ($child_el['type'] == 'category') { $row_count++; } } // Print category total at the end if aggregation position is "last" (1) if (!empty($category_total_item) && $aggregation_position) { $html_children = array_merge($html_children, $category_total_item); } // Determine if we are at the root if (isset($element['object']->grade_item) && $element['object']->grade_item->is_course_item()) { $root = true; } $levelclass = "level{$level} level" . ($level % 2 ? 'odd' : 'even'); $courseclass = ''; if ($level == 1) { $courseclass = 'coursecategory'; } $row = new html_table_row(); $row->id = 'grade-item-' . $eid; $row->attributes['class'] = $courseclass . ' category ' . $dimmed; foreach ($rowclasses as $class) { $row->attributes['class'] .= ' ' . $class; } $headercell = new html_table_cell(); $headercell->header = true; $headercell->scope = 'row'; $headercell->attributes['title'] = $object->stripped_name; $headercell->attributes['class'] = 'cell column-rowspan rowspan ' . $levelclass; $headercell->rowspan = $row_count + 1; $row->cells[] = $headercell; foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving)) { $row->cells[] = $column->get_category_cell($category, $levelclass, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'moveaction' => $moveaction, 'eid' => $eid)); } } $returnrows[] = $row; $returnrows = array_merge($returnrows, $html_children); // Print a coloured row to show the end of the category across the table $endcell = new html_table_cell(); $endcell->colspan = 19 - $level; $endcell->attributes['class'] = 'emptyrow colspan ' . $levelclass; $returnrows[] = new html_table_row(array($endcell)); } else { // Dealing with a grade item $item = grade_item::fetch(array('id' => $object->id)); $element['type'] = 'item'; $element['object'] = $item; $categoryitemclass = ''; if ($item->itemtype == 'category') { $categoryitemclass = 'categoryitem'; } if ($item->itemtype == 'course') { $categoryitemclass = 'courseitem'; } $dimmed = $item->is_hidden() ? "dimmed_text" : ""; $gradeitemrow = new html_table_row(); $gradeitemrow->id = 'grade-item-' . $eid; $gradeitemrow->attributes['class'] = $categoryitemclass . ' item ' . $dimmed; foreach ($rowclasses as $class) { $gradeitemrow->attributes['class'] .= ' ' . $class; } foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving)) { $gradeitemrow->cells[] = $column->get_item_cell($item, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'element' => $element, 'eid' => $eid, 'moveaction' => $moveaction, 'itemtype' => $object->itemtype)); } } $returnrows[] = $gradeitemrow; } return $returnrows; }
function validation($data, $files) { global $COURSE; $gradeitem = false; if ($data['id']) { $gradecategory = grade_category::fetch(array('id' => $data['id'])); $gradeitem = $gradecategory->load_grade_item(); } $errors = parent::validation($data, $files); if (array_key_exists('grade_item_gradetype', $data) and $data['grade_item_gradetype'] == GRADE_TYPE_SCALE) { if (empty($data['grade_item_scaleid'])) { $errors['grade_item_scaleid'] = get_string('missingscale', 'grades'); } } if (array_key_exists('grade_item_grademin', $data) and array_key_exists('grade_item_grademax', $data)) { if (($data['grade_item_grademax'] != 0 or $data['grade_item_grademin'] != 0) and ($data['grade_item_grademax'] == $data['grade_item_grademin'] or $data['grade_item_grademax'] < $data['grade_item_grademin'])) { $errors['grade_item_grademin'] = get_string('incorrectminmax', 'grades'); $errors['grade_item_grademax'] = get_string('incorrectminmax', 'grades'); } } if ($data['id'] && $gradeitem->has_overridden_grades()) { if ($gradeitem->gradetype == GRADE_TYPE_VALUE) { if (grade_floats_different($data['grade_item_grademin'], $gradeitem->grademin) || grade_floats_different($data['grade_item_grademax'], $gradeitem->grademax)) { if (empty($data['grade_item_rescalegrades'])) { $errors['grade_item_rescalegrades'] = get_string('mustchooserescaleyesorno', 'grades'); } } } } return $errors; }
/** * Saves a gradebook (a set of grade items and scores related to a course), * also creates the categories based on the item type * * @param object $gradebook an object with at least course_id and items set * items should contain grade_items (courseid. categoryid, name, scores) * scores should contain grade_grade (user_id, score) * @return stdClass the saved gradebook with all items and scores in the same structure, * errors are recorded as grade_item->errors and score->error * @throws InvalidArgumentException */ public static function save_gradebook($gradebook) { global $CFG; if (!$gradebook) { throw new InvalidArgumentException("gradebook must be set"); } if (!isset($gradebook->course_id)) { throw new InvalidArgumentException("gradebook->course_id must be set"); } if (!isset($gradebook->items) || empty($gradebook->items)) { throw new InvalidArgumentException("gradebook->items must be set and include items"); } $gb_saved = new stdClass(); $gb_saved->items = array(); $gb_saved->course_id = $gradebook->course_id; $course = self::get_course($gradebook->course_id); if (!$course) { throw new InvalidArgumentException("No course found with course_id ({$gradebook->course_id})"); } $gb_saved->course = $course; // extra permissions check on gradebook manage/update $user_id = self::require_user(); if (class_exists('context_course')) { // for Moodle 2.2+ $context = context_course::instance($course->id); } else { /** @noinspection PhpDeprecationInspection */ $context = get_context_instance(CONTEXT_COURSE, $course->id); // deprecated } if (!$context || !has_capability('moodle/grade:manage', $context, $user_id)) { throw new InvalidArgumentException("User ({$user_id}) cannot manage the gradebook in course id={$course->id} (" . var_export($course, true) . "), context: " . var_export($context, true)); } // attempt to get the default iclicker category first $default_iclicker_category = grade_category::fetch(array('courseid' => $gradebook->course_id, 'fullname' => self::GRADE_CATEGORY_NAME)); $default_iclicker_category_id = $default_iclicker_category ? $default_iclicker_category->id : null; //echo "\n\nGRADEBOOK: ".var_export($gradebook); // iterate through and save grade items by calling other method if (!empty($gradebook->items)) { $saved_items = array(); $number = 0; foreach ($gradebook->items as $grade_item) { // check for this category $item_category_name = self::GRADE_CATEGORY_NAME; if (!empty($grade_item->type) && self::GRADE_CATEGORY_NAME != $grade_item->type) { $item_category_name = $grade_item->type; $item_category = grade_category::fetch(array('courseid' => $gradebook->course_id, 'fullname' => $item_category_name)); if (!$item_category) { // create the category $params = array('courseid' => $gradebook->course_id, 'fullname' => $item_category_name); $grade_category = new grade_category($params, false); // Use default aggregation type. $grade_category->aggregation = $CFG->grade_aggregation; $grade_category->insert(self::GRADE_LOCATION_STR); $item_category_id = $grade_category->id; } else { $item_category_id = $item_category->id; } } else { // use default if (!$default_iclicker_category_id) { // create the category $params = array('courseid' => $gradebook->course_id, 'fullname' => self::GRADE_CATEGORY_NAME); $grade_category = new grade_category($params, false); // Use default aggregation type. $grade_category->aggregation = $CFG->grade_aggregation; $grade_category->insert(self::GRADE_LOCATION_STR); $default_iclicker_category_id = $grade_category->id; } $item_category_id = $default_iclicker_category_id; } $grade_item->categoryid = $item_category_id; $grade_item->typename = $item_category_name; $grade_item->courseid = $gradebook->course_id; $grade_item->item_number = $number; $saved_grade_item = self::save_grade_item($grade_item); $saved_items[] = $saved_grade_item; $number++; } $gb_saved->items = $saved_items; } $gb_saved->default_category_id = $default_iclicker_category_id; //echo "\n\nRESULT: ".var_export($gb_saved); return $gb_saved; }
/** * Return the course level grade_category object * * @param int $courseid The Course ID * @return grade_category Returns the course level grade_category instance */ public static function fetch_course_category($courseid) { if (empty($courseid)) { debugging('Missing course id!'); return false; } // course category has no parent if ($course_category = grade_category::fetch(array('courseid' => $courseid, 'parent' => null))) { return $course_category; } // create a new one $course_category = new grade_category(); $course_category->insert_course_category($courseid); return $course_category; }
/** * Determines whether the grade tree item can be displayed. * This is particularly targeted for grade categories that have no total (None) when rendering the grade tree. * It checks if the grade tree item is of type 'category', and makes sure that the category, or at least one of children, * can be output. * * @param array $element The grade category element. * @return bool True if the grade tree item can be displayed. False, otherwise. */ public static function can_output_item($element) { $canoutput = true; if ($element['type'] === 'category') { $object = $element['object']; $category = grade_category::fetch(array('id' => $object->id)); // Category has total, we can output this. if ($category->get_grade_item()->gradetype != GRADE_TYPE_NONE) { return true; } // Category has no total and has no children, no need to output this. if (empty($element['children'])) { return false; } $canoutput = false; // Loop over children and make sure at least one child can be output. foreach ($element['children'] as $child) { $canoutput = self::can_output_item($child); if ($canoutput) { break; } } } return $canoutput; }
$grade_item->update(); grade_regrade_final_grades($courseid); // Grade category checkbox inputs } elseif (preg_match('/aggregate(onlygraded|subcats|outcomes)_original_([0-9]*)/', $key, $matches) && confirm_sesskey()) { $setting = optional_param('aggregate' . $matches[1] . '_' . $matches[2], null, PARAM_BOOL); $original_value = required_param($matches[0], PARAM_BOOL); $a->id = $matches[2]; $newvalue = null; if ($original_value == 1 && is_null($setting)) { $newvalue = 0; } elseif ($original_value == 0 && $setting == 1) { $newvalue = 1; } else { continue; } $grade_category = grade_category::fetch(array('id' => $a->id, 'courseid' => $courseid)); $grade_category->{'aggregate' . $matches[1]} = $newvalue; $grade_category->update(); grade_regrade_final_grades($courseid); } } } // Print Table of categories and items print_box_start('gradetreebox generalbox'); echo '<form id="gradetreeform" method="post" action="' . $returnurl . '">'; echo '<div>'; echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />'; // Build up an array of categories for move drop-down (by reference) $categories = array(); $level = 0; $row_count = 0;
/** * Return the top most course category. * @static * @return object grade_category instance for course grade */ function fetch_course_category($courseid) { // course category has no parent if ($course_category = grade_category::fetch(array('courseid' => $courseid, 'parent' => null))) { return $course_category; } // create a new one $course_category = new grade_category(); $course_category->insert_course_category($courseid); return $course_category; }
/** * Tests the gradebookservice update grade with cases that should * result in success. * * @return void */ public function test_update_grade_update_item() { global $DB; $callback = 'block_mhaairs_gradebookservice_external::update_grade'; $this->set_user('admin'); // CREATE/UPDATE. $cases = $this->get_cases('tc_update_grade'); foreach ($cases as $case) { if (!empty($case->hidden)) { continue; } try { $result = call_user_func_array($callback, $case->servicedata); $this->assertEquals($case->result, $result); } catch (Exception $e) { $result = get_class($e); $this->assertEquals($case->result, $result); continue; } // Fetch the item. $giparams = array('itemtype' => 'manual', 'itemmodule' => 'mhaairs', 'iteminstance' => $case->iteminstance, 'courseid' => $this->course->id, 'itemnumber' => $case->itemnumber); $gitem = grade_item::fetch($giparams); if (is_numeric($case->result) and (int) $case->result === 0) { // Verify successful update. $this->assertInstanceOf('grade_item', $gitem); $maxgrade = !empty($case->item_grademax) ? (int) $case->item_grademax : 100; $this->assertEquals($maxgrade, $gitem->grademax); if (!empty($case->item_categoryid)) { // Fetch the category. $fetchparams = array('fullname' => $case->item_categoryid, 'courseid' => $this->course->id); $category = grade_category::fetch($fetchparams); $categoryid = $category->id; $this->assertEquals($gitem->categoryid, $categoryid); } } else { // Verify failed update. $this->assertEquals(false, $gitem); } } }
function definition_after_data() { global $CFG; $mform =& $this->_form; $checkbox_values = array(get_string('no'), get_string('yes')); if ($CFG->grade_aggregation != -1) { $agg_el =& $mform->getElement('aggregation'); $agg_el->setValue($this->aggregation_types[$CFG->grade_aggregation]); } if ($CFG->grade_aggregateonlygraded != -1) { $agg_el =& $mform->getElement('aggregateonlygraded'); $agg_el->setValue($checkbox_values[$CFG->grade_aggregateonlygraded]); } if ($CFG->grade_aggregateoutcomes != -1) { $agg_el =& $mform->getElement('aggregateoutcomes'); $agg_el->setValue($checkbox_values[$CFG->grade_aggregateoutcomes]); } if ($CFG->grade_aggregatesubcats != -1) { $agg_el =& $mform->getElement('aggregatesubcats'); $agg_el->setValue($checkbox_values[$CFG->grade_aggregatesubcats]); } if ($CFG->grade_keephigh != -1) { $agg_el =& $mform->getElement('keephigh'); $agg_el->setValue($this->keepdrop_options[$CFG->grade_keephigh]); } if ($CFG->grade_droplow != -1) { $agg_el =& $mform->getElement('droplow'); $agg_el->setValue($this->keepdrop_options[$CFG->grade_droplow]); } if ($id = $mform->getElementValue('id')) { $grade_category = grade_category::fetch(array('id' => $id)); $grade_item = $grade_category->load_grade_item(); if ($grade_item->is_calculated()) { // following elements are ignored when calculation formula used if ($mform->elementExists('aggregation')) { $mform->removeElement('aggregation'); } if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } if ($mform->elementExists('aggregateonlygraded')) { $mform->removeElement('aggregateonlygraded'); } if ($mform->elementExists('aggregateoutcomes')) { $mform->removeElement('aggregateoutcomes'); } if ($mform->elementExists('aggregatesubcats')) { $mform->removeElement('aggregatesubcats'); } } } }
public function get_category_start_date($course, $user, $category) { $itemtype = 'mod'; $itemmodule = ''; $iteminstance = ''; $courseid = $course->id; $iteminstance = $category->iteminstance; $category_start_date = NULL; $course_category = grade_category::fetch(array('courseid' => $courseid, 'id' => $iteminstance)); $grade_items = $course_category->get_children(); foreach ($grade_items as $grade => $grade_value) { $grade_item = $grade_value["object"]; $start_date = $this->get_activity_start_date($course, $user, $grade_item); if ($category_start_date > $start_date && $start_date != NULL || $category_start_date == NULL) { $category_start_date = $start_date; } } // echo $category_start_date ? $category_start_date->format('d-m-Y') : "-"; return $category_start_date; }
$grade_item->set_parent($item->categoryid); $grade_item->move_after_sortorder($item->sortorder); } $grade_items[] = $grade_item; } } // Create a grade_category to represent this module, if outcomes have been attached if (!empty($grade_items)) { // Add the module's normal grade_item as a child of this category $item_params = array('itemtype' => 'mod', 'itemmodule' => $fromform->modulename, 'iteminstance' => $fromform->instance, 'itemnumber' => 0, 'courseid' => $COURSE->id); $item = grade_item::fetch($item_params); // Only create the category if it will contain at least 2 items if ($item or count($grade_items) > 1) { // If we are here it means there is at least 1 outcome $cat_params = array('courseid' => $COURSE->id, 'fullname' => $fromform->name); $grade_category = grade_category::fetch($cat_params); if (!$grade_category) { $grade_category = new grade_category($cat_params); $grade_category->courseid = $COURSE->id; $grade_category->fullname = $fromform->name; $grade_category->insert(); } $sortorder = $grade_category->sortorder; if ($item) { $item->set_parent($grade_category->id); $sortorder = $item->sortorder; } // Add the outcomes as children of this category foreach ($grade_items as $gi) { $gi->set_parent($grade_category->id); $gi->move_after_sortorder($sortorder);
/** * Recursive function for building the table holding the grade categories and items, * with CSS indentation and styles. * * @param array $element The current tree element being rendered * @param boolean $totals Whether or not to print category grade items (category totals) * @param array $parents An array of parent categories for the current element (used for indentation and row classes) * * @return string HTML */ function build_html_tree($element, $totals, $parents, &$categories, $level, &$row_count) { global $CFG, $COURSE, $USER; $object = $element['object']; $eid = $element['eid']; $object->name = $this->gtree->get_element_header($element, true, true, false); $object->stripped_name = $this->gtree->get_element_header($element, false, false, false); $is_category_item = false; if ($element['type'] == 'categoryitem' || $element['type'] == 'courseitem') { $is_category_item = true; } $rowclasses = ''; foreach ($parents as $parent_eid) { $rowclasses .= " {$parent_eid} "; } $actions = ''; if (!$is_category_item) { $actions .= $this->gtree->get_edit_icon($element, $this->gpr); } $actions .= $this->gtree->get_calculation_icon($element, $this->gpr); if ($element['type'] == 'item' or $element['type'] == 'category' and $element['depth'] > 1) { if ($this->element_deletable($element)) { $actions .= '<a href="index.php?id=' . $COURSE->id . '&action=delete&eid=' . $eid . '&sesskey=' . sesskey() . '"><img src="' . $CFG->pixpath . '/t/delete.gif" class="iconsmall" alt="' . get_string('delete') . '" title="' . get_string('delete') . '"/></a>'; } $actions .= '<a href="index.php?id=' . $COURSE->id . '&action=moveselect&eid=' . $eid . '&sesskey=' . sesskey() . '"><img src="' . $CFG->pixpath . '/t/move.gif" class="iconsmall" alt="' . get_string('move') . '" title="' . get_string('move') . '"/></a>'; } $actions .= $this->gtree->get_hiding_icon($element, $this->gpr); $actions .= $this->gtree->get_locking_icon($element, $this->gpr); $mode = $USER->gradeediting[$COURSE->id] ? 'advanced' : 'simple'; $html = ''; $root = false; $id = required_param('id', PARAM_INT); /// prepare move target if needed $last = ''; /// print the list items now if ($this->moving == $eid) { // do not diplay children return '<tr><td colspan="12" class="' . $element['type'] . ' moving">' . $object->name . ' (' . get_string('move') . ')</td></tr>'; } if ($element['type'] == 'category') { $level++; $categories[$object->id] = $object->stripped_name; $category = grade_category::fetch(array('id' => $object->id)); $item = $category->get_grade_item(); // Add aggregation coef input if not a course item and if parent category has correct aggregation type $dimmed = $item->is_hidden() ? " dimmed " : ""; // Before we print the category's row, we must find out how many rows will appear below it (for the filler cell's rowspan) $aggregation_position = grade_get_setting($COURSE->id, 'aggregationposition', $CFG->grade_aggregationposition); $category_total_data = null; // Used if aggregationposition is set to "last", so we can print it last $html_children = ''; $row_count = 0; foreach ($element['children'] as $child_el) { $moveto = ''; if (empty($child_el['object']->itemtype)) { $child_el['object']->itemtype = false; } if (($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') && !$totals) { continue; } $child_eid = $child_el['eid']; $first = ''; if ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') { $first = '&first=1'; $child_eid = $eid; } if ($this->moving && $this->moving != $child_eid) { $strmove = get_string('move'); $strmovehere = get_string('movehere'); $actions = ''; // no action icons when moving $moveto = '<tr><td colspan="12"><a href="index.php?id=' . $COURSE->id . '&action=move&eid=' . $this->moving . '&moveafter=' . $child_eid . '&sesskey=' . sesskey() . $first . '"><img class="movetarget" src="' . $CFG->wwwroot . '/pix/movehere.gif" alt="' . $strmovehere . '" title="' . s($strmovehere) . '" /></a></td></tr>'; } $newparents = $parents; $newparents[] = $eid; $row_count++; $child_row_count = 0; // If moving, do not print course and category totals, but still print the moveto target box if ($this->moving && ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category')) { $html_children .= $moveto; } elseif ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') { // We don't build the item yet because we first need to know the deepest level of categories (for category/name colspans) $category_total_item = $this->build_html_tree($child_el, $totals, $newparents, $categories, $level, $child_row_count); if (!$aggregation_position) { $html_children .= $category_total_item; } } else { $html_children .= $this->build_html_tree($child_el, $totals, $newparents, $categories, $level, $child_row_count) . $moveto; if ($this->moving) { $row_count++; } } $row_count += $child_row_count; // If the child is a category, increment row_count by one more (for the extra coloured row) if ($child_el['type'] == 'category') { $row_count++; } } // Print category total at the end if aggregation position is "last" (1) if (!empty($category_total_item) && $aggregation_position) { $html_children .= $category_total_item; } // now build the header if (isset($element['object']->grade_item) && $element['object']->grade_item->is_course_item()) { // Reduce width if advanced elements are not shown $width_style = ''; if ($mode == 'simple') { $width_style = ' style="width:auto;" '; } $html .= '<table cellpadding="5" class="generaltable" ' . $width_style . '> <tr>'; foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving) && !$column->is_hidden($mode)) { $html .= $column->get_header_cell(); } } $html .= '</tr>'; $root = true; } $row_count_offset = 0; if (empty($category_total_item) && !$this->moving) { $row_count_offset = -1; } $levelclass = " level{$level} "; $html .= ' <tr class="category ' . $dimmed . $rowclasses . '"> <th scope="row" title="' . s($object->stripped_name) . '" class="cell rowspan ' . $levelclass . '" rowspan="' . ($row_count + 1 + $row_count_offset) . '"></th>'; foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving) && !$column->is_hidden($mode)) { $html .= $column->get_category_cell($category, $levelclass, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'eid' => $eid)); } } $html .= '</tr>'; $html .= $html_children; // Print a coloured row to show the end of the category accross the table $html .= '<tr><td colspan="' . (19 - $level) . '" class="colspan ' . $levelclass . '"></td></tr>'; } else { // Dealing with a grade item $item = grade_item::fetch(array('id' => $object->id)); $element['type'] = 'item'; $element['object'] = $item; // Determine aggregation coef element $dimmed = $item->is_hidden() ? " dimmed_text " : ""; $html .= '<tr class="item' . $dimmed . $rowclasses . '">'; foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving) && !$column->is_hidden($mode)) { $html .= $column->get_item_cell($item, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'element' => $element, 'eid' => $eid, 'itemtype' => $object->itemtype)); } } $html .= '</tr>'; } if ($root) { $html .= "</table>\n"; } return $html; }
function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; $somecat = new grade_category(); foreach ($somecat->forceable as $property) { if ((int) $CFG->{"grade_{$property}_flag"} & 1) { if ($mform->elementExists($property)) { if (empty($CFG->grade_hideforcedsettings)) { $mform->hardFreeze($property); } else { if ($mform->elementExists($property)) { $mform->removeElement($property); } } } } } if ($CFG->grade_droplow > 0) { if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } } else { if ($CFG->grade_keephigh > 0) { if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } } } if ($id = $mform->getElementValue('id')) { $grade_category = grade_category::fetch(array('id' => $id)); $grade_item = $grade_category->load_grade_item(); // remove agg coef if not used if ($grade_category->is_course_category()) { if ($mform->elementExists('parentcategory')) { $mform->removeElement('parentcategory'); } if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { // if we wanted to change parent of existing category - we would have to verify there are no circular references in parents!!! if ($mform->elementExists('parentcategory')) { $mform->hardFreeze('parentcategory'); } $parent_category = $grade_category->get_parent_category(); $parent_category->apply_forced_settings(); if (!$parent_category->is_aggregationcoef_used()) { if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { //fix label if needed $agg_el =& $mform->getElement('aggregationcoef'); $aggcoef = ''; if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) { $aggcoef = 'aggregationcoefweight'; } else { if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) { $aggcoef = 'aggregationcoefextra'; } } if ($aggcoef !== '') { $agg_el->setLabel(get_string($aggcoef, 'grades')); $mform->setHelpButton('aggregationcoef', array('aggregationcoef', get_string('aggregationcoef', 'grades'), 'grade'), true); } } } if ($grade_item->is_calculated()) { // following elements are ignored when calculation formula used if ($mform->elementExists('aggregation')) { $mform->removeElement('aggregation'); } if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } if ($mform->elementExists('aggregateonlygraded')) { $mform->removeElement('aggregateonlygraded'); } if ($mform->elementExists('aggregateoutcomes')) { $mform->removeElement('aggregateoutcomes'); } if ($mform->elementExists('aggregatesubcats')) { $mform->removeElement('aggregatesubcats'); } } // If it is a course category, remove the "required" rule from the "fullname" element if ($grade_category->is_course_category()) { unset($mform->_rules['fullname']); $key = array_search('fullname', $mform->_required); unset($mform->_required[$key]); } // If it is a course category and its fullname is ?, show an empty field if ($grade_category->is_course_category() && $mform->getElementValue('fullname') == '?') { $mform->setDefault('fullname', ''); } } // no parent header for course category if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) { $mform->removeElement('headerparent'); } }
/** * Sets this item's categoryid. A generic method shared by objects that have a parent id of some kind. * * @param int $parentid The ID of the new parent * @param bool $updateaggregationfields Whether or not to convert the aggregation fields when switching between category. * Set this to false when the aggregation fields have been updated in prevision of the new * category, typically when the item is freshly created. * @return bool True if success */ public function set_parent($parentid, $updateaggregationfields = true) { if ($this->is_course_item() or $this->is_category_item()) { print_error('cannotsetparentforcatoritem'); } if ($this->categoryid == $parentid) { return true; } // find parent and check course id if (!($parent_category = grade_category::fetch(array('id' => $parentid, 'courseid' => $this->courseid)))) { return false; } $currentparent = $this->load_parent_category(); if ($updateaggregationfields) { $this->set_aggregation_fields_for_aggregation($currentparent->aggregation, $parent_category->aggregation); } $this->force_regrading(); // set new parent $this->categoryid = $parent_category->id; $this->parent_category =& $parent_category; return $this->update(); }
/** * Sets this item's categoryid. A generic method shared by objects that have a parent id of some kind. * @param int $parentid * @return boolean success; */ function set_parent($parentid) { if ($this->is_course_item() or $this->is_category_item()) { error('Can not set parent for category or course item!'); } if ($this->categoryid == $parentid) { return true; } // find parent and check course id if (!($parent_category = grade_category::fetch(array('id' => $parentid, 'courseid' => $this->courseid)))) { return false; } // MDL-19407 If moving from a non-SWM category to a SWM category, convert aggregationcoef to 0 $currentparent = $this->load_parent_category(); if ($currentparent->aggregation != GRADE_AGGREGATE_WEIGHTED_MEAN2 && $parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) { $this->aggregationcoef = 0; } $this->force_regrading(); // set new parent $this->categoryid = $parent_category->id; $this->parent_category =& $parent_category; return $this->update(); }
function quick_dump() { global $CFG; require_once $CFG->dirroot . '/lib/excellib.class.php'; // $export_tracking = $this->track_exports(); $strgrades = get_string('grades'); $accuratetotals = get_user_preferences('accuratepointtotals') == null ? 1 : 0; /// Calculate file name $downloadfilename = clean_filename("{$this->course->shortname} {$strgrades}.xls"); /// Creating a workbook $workbook = new MoodleExcelWorkbook("-"); /// Sending HTTP headers $workbook->send($downloadfilename); /// Adding the worksheet $myxls =& $workbook->add_worksheet($strgrades); /// Print names of all the fields $myxls->write_string(0, 0, get_string("firstname")); $myxls->write_string(0, 1, get_string("lastname")); $myxls->write_string(0, 2, get_string("idnumber")); $myxls->write_string(0, 3, get_string("email")); $pos = 4; // write out column headers foreach ($this->gtree->items as $grade_item) { // $myxls->write_string(0, $pos++, $this->format_column_name($grade_item)); switch ($grade_item->itemtype) { case 'category': $grade_item->item_category = grade_category::fetch(array('id' => $grade_item->iteminstance)); // $grade_item->load_category(); $myxls->write_string(0, $pos++, $grade_item->item_category->fullname . ' Category total'); break; case 'course': $myxls->write_string(0, $pos++, 'Course total'); break; default: $myxls->write_string(0, $pos++, $grade_item->itemname); } /// add a column_feedback column if (isset($this->export_feedback) and $this->export_feedback) { // $myxls->write_string(0, $pos++, $this->format_column_name($grade_item, true)); $myxls->write_string(0, $pos++, $grade_item->itemname); } } // write out range row $myxls->write_string(1, 2, 'Maximum grade->'); $pos = 4; foreach ($this->gtree->items as $grade_item) { // $myxls->write_string(0, $pos++, $this->format_column_name($grade_item)); $myxls->write_number(1, $pos++, $grade_item->grademax); // $myxls->write_number($i,$j++,$gradestr); /// add a column_feedback column if (isset($this->export_feedback) and $this->export_feedback) { // $myxls->write_string(0, $pos++, $this->format_column_name($grade_item, true)); $myxls->write_string(1, $pos++, $grade_item->name); } } // write out weights row $myxls->write_string(2, 2, 'Weight->'); $pos = 4; foreach ($this->gtree->items as $grade_item) { if (isset($this->gtree->parents[$grade_item->id]->id) && $this->gtree->parents[$grade_item->id]->agg == GRADE_AGGREGATE_WEIGHTED_MEAN) { $myxls->write_number(2, $pos++, $grade_item->aggregationcoef); // $myxls->write_string(1, $pos++, format_float($grade_item->aggregationcoef,0)); } else { $myxls->write_string(2, $pos++, ""); } /// add a column_feedback column if (isset($this->export_feedback) and $this->export_feedback) { $myxls->write_string(2, $pos++, $grade_item->name); } } /// Print all the lines of data. $i = 2; // $geub = new grade_export_update_buffer(); // $gui = new graded_users_iterator($this->course, $this->columns, $this->groupid); // $gui->init(); foreach ($this->users as $key => $user) { $i++; // $user = $userdata->user; $myxls->write_string($i, 0, $user->firstname); $myxls->write_string($i, 1, $user->lastname); $myxls->write_string($i, 2, $user->idnumber); $myxls->write_string($i, 3, $user->email); // $myxls->write_string($i,3,$user->institution); // $myxls->write_string($i,4,$user->department); // $myxls->write_string($i,3,$user->email); $j = 4; foreach ($this->gtree->items as $itemid => $item) { // if ($export_tracking) { // $status = $geub->track($grade); // } $grade = $this->grades[$key][$itemid]; $gradeval = $grade->finalgrade; // if gradeeditalways then we only want the first displaytype (in case multiple displaytypes are requested) $gradedisplaytype = (int) substr((string) $item->get_displaytype(), 0, 1); // if we have an accumulated total points that's not accurately reflected in the db, then we want to display the ACCURATE number if ($gradedisplaytype == GRADE_DISPLAY_TYPE_REAL && isset($this->grades[$userid][$grade->itemid]->cat_item)) { $items = $this->gtree->items; $grade_values = $this->grades[$userid][$grade->itemid]->cat_item; $grade_maxes = $this->grades[$userid][$grade->itemid]->cat_max; $this_cat = $this->gtree->items[$grade->itemid]->get_item_category(); limit_item($this_cat, $items, $grade_values, $grade_maxes); $gradeval = array_sum($grade_values); $item->grademax = array_sum($grade_maxes); } // is calculating accurate totals store the earned_total for this item to its parent, if there is one if (!$grade->is_hidden() && $gradeval != null && $this->accuratetotals) { $this->grades[$userid][$this->gtree->parents[$grade->itemid]->id]->cat_item[$grade->itemid] = $gradeval; $this->grades[$userid][$this->gtree->parents[$grade->itemid]->id]->cat_max[$grade->itemid] = $grade->rawgrademax; } $gradestr = grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null); /* if ($gradedisplaytype == GRADE_DISPLAY_TYPE_REAL && $this->accuratetotals) { $gradestr = grade_format_gradevalue($grade->earned_total, $item, true, $gradedisplaytype, null); } else { $gradestr = grade_format_gradevalue($grade->finalgrade, $item, true, $gradedisplaytype, null); } */ if (is_percentage($gradestr)) { $myxls->write_number($i, $j++, $gradestr * 0.01); // $myxls->write_number($i,$j++,substr(trim($gradestr),0,strlen(trim($gradestr))-1), array(num_format=>'Percent')); } else { if (is_numeric($gradestr)) { $myxls->write_number($i, $j++, $gradestr); } else { $myxls->write_string($i, $j++, $gradestr); } } /* // writing feedback if requested if ($this->export_feedback) { $myxls->write_string($i, $j++, $this->format_feedback($userdata->feedbacks[$itemid])); } * */ } } // $gui->close(); // $geub->close(); /// Close the workbook $workbook->close(); exit; }
$item->aggregationcoef = $item->aggregationcoef == 0 ? 0 : 1; } else { $item->aggregationcoef = format_float($item->aggregationcoef, 4); } if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { $item->aggregationcoef2 = format_float($item->aggregationcoef2 * 100.0); } $item->cancontrolvisibility = $grade_item->can_control_visibility(); $mform = new edit_item_form(null, array('current' => $item, 'gpr' => $gpr)); if ($mform->is_cancelled()) { redirect($returnurl); } else { if ($data = $mform->get_data(false)) { // This is a new item, and the category chosen is different than the default category. if (empty($grade_item->id) && isset($data->parentcategory) && $parent_category->id != $data->parentcategory) { $parent_category = grade_category::fetch(array('id' => $data->parentcategory)); } // If unset, give the aggregation values a default based on parent aggregation method. $defaults = grade_category::get_default_aggregation_coefficient_values($parent_category->aggregation); if (!isset($data->aggregationcoef) || $data->aggregationcoef == '') { $data->aggregationcoef = $defaults['aggregationcoef']; } if (!isset($data->weightoverride)) { $data->weightoverride = $defaults['weightoverride']; } if (!isset($data->gradepass) || $data->gradepass == '') { $data->gradepass = 0; } if (!isset($data->grademin) || $data->grademin == '') { $data->grademin = 0; }
/** * Test can_output_item. */ public function test_can_output_item() { $this->resetAfterTest(); $generator = $this->getDataGenerator(); // Course level grade category. $course = $generator->create_course(); // Grade tree looks something like: // - Test course (Rendered). $gradetree = grade_category::fetch_course_tree($course->id); $this->assertTrue(grade_tree::can_output_item($gradetree)); // Add a grade category with default settings. $generator->create_grade_category(array('courseid' => $course->id)); // Grade tree now looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). $gradetree = grade_category::fetch_course_tree($course->id); $this->assertNotEmpty($gradetree['children']); foreach ($gradetree['children'] as $child) { $this->assertTrue(grade_tree::can_output_item($child)); } // Add a grade category with grade type = None. $nototalcategory = 'No total category'; $nototalparams = ['courseid' => $course->id, 'fullname' => $nototalcategory, 'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN]; $nototal = $generator->create_grade_category($nototalparams); $catnototal = grade_category::fetch(array('id' => $nototal->id)); // Set the grade type of the grade item associated to the grade category. $catitemnototal = $catnototal->load_grade_item(); $catitemnototal->gradetype = GRADE_TYPE_NONE; $catitemnototal->update(); // Grade tree looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). // -- No total category (Not rendered). $gradetree = grade_category::fetch_course_tree($course->id); foreach ($gradetree['children'] as $child) { if ($child['object']->fullname == $nototalcategory) { $this->assertFalse(grade_tree::can_output_item($child)); } else { $this->assertTrue(grade_tree::can_output_item($child)); } } // Add another grade category with default settings under 'No total category'. $normalinnototalparams = ['courseid' => $course->id, 'fullname' => 'Normal category in no total category', 'parent' => $nototal->id]; $generator->create_grade_category($normalinnototalparams); // Grade tree looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). // -- No total category (Rendered). // --- Normal category in no total category (Rendered). $gradetree = grade_category::fetch_course_tree($course->id); foreach ($gradetree['children'] as $child) { // All children are now visible. $this->assertTrue(grade_tree::can_output_item($child)); if (!empty($child['children'])) { foreach ($child['children'] as $grandchild) { $this->assertTrue(grade_tree::can_output_item($grandchild)); } } } // Add a grade category with grade type = None. $nototalcategory2 = 'No total category 2'; $nototal2params = ['courseid' => $course->id, 'fullname' => $nototalcategory2, 'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN]; $nototal2 = $generator->create_grade_category($nototal2params); $catnototal2 = grade_category::fetch(array('id' => $nototal2->id)); // Set the grade type of the grade item associated to the grade category. $catitemnototal2 = $catnototal2->load_grade_item(); $catitemnototal2->gradetype = GRADE_TYPE_NONE; $catitemnototal2->update(); // Add a category with no total under 'No total category'. $nototalinnototalcategory = 'Category with no total in no total category'; $nototalinnototalparams = ['courseid' => $course->id, 'fullname' => $nototalinnototalcategory, 'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN, 'parent' => $nototal2->id]; $nototalinnototal = $generator->create_grade_category($nototalinnototalparams); $catnototalinnototal = grade_category::fetch(array('id' => $nototalinnototal->id)); // Set the grade type of the grade item associated to the grade category. $catitemnototalinnototal = $catnototalinnototal->load_grade_item(); $catitemnototalinnototal->gradetype = GRADE_TYPE_NONE; $catitemnototalinnototal->update(); // Grade tree looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). // -- No total category (Rendered). // --- Normal category in no total category (Rendered). // -- No total category 2 (Not rendered). // --- Category with no total in no total category (Not rendered). $gradetree = grade_category::fetch_course_tree($course->id); foreach ($gradetree['children'] as $child) { if ($child['object']->fullname == $nototalcategory2) { $this->assertFalse(grade_tree::can_output_item($child)); } else { $this->assertTrue(grade_tree::can_output_item($child)); } if (!empty($child['children'])) { foreach ($child['children'] as $grandchild) { if ($grandchild['object']->fullname == $nototalinnototalcategory) { $this->assertFalse(grade_tree::can_output_item($grandchild)); } else { $this->assertTrue(grade_tree::can_output_item($grandchild)); } } } } }
/** * Sets this item's categoryid. A generic method shared by objects that have a parent id of some kind. * @param int $parentid * @return boolean success; */ function set_parent($parentid) { if ($this->is_course_item() or $this->is_category_item()) { error('Can not set parent for category or course item!'); } if ($this->categoryid == $parentid) { return true; } // find parent and check course id if (!($parent_category = grade_category::fetch(array('id' => $parentid, 'courseid' => $this->courseid)))) { return false; } $this->force_regrading(); // set new parent $this->categoryid = $parent_category->id; $this->parent_category =& $parent_category; return $this->update(); }
/** * Preprocesses the creation of a grade item. Converts gradetype text to a number. * @param array $data * @return array */ protected function preprocess_grade_item($data) { global $CFG; require_once "{$CFG->libdir}/grade/constants.php"; if (isset($data['gradetype'])) { $data['gradetype'] = constant("GRADE_TYPE_" . strtoupper($data['gradetype'])); } if (!empty($data['category']) && !empty($data['courseid'])) { $cat = grade_category::fetch(array('fullname' => $data['category'], 'courseid' => $data['courseid'])); if (!$cat) { throw new Exception('Could not resolve category with name "' . $data['category'] . '"'); } unset($data['category']); $data['categoryid'] = $cat->id; } return $data; }
/** * Recurses through the entire grade tree to find and return the maximum depth of the tree. * This should be run only once from the root element (course category), and is used for the * indentation of the Name column's cells (colspan) * * @param array $element An array of values representing a grade tree's element (all grade items in this case) * @param int $level The level of the current recursion * @param int $deepest_level A value passed to each subsequent level of recursion and incremented if $level > $deepest_level * @return int Deepest level */ function get_deepest_level($element, $level = 0, $deepest_level = 1) { $object = $element['object']; $level++; $coefstring = $element['object']->get_coefstring(); if ($element['type'] == 'category') { if ($coefstring == 'aggregationcoefweight' || $coefstring == 'aggregationcoefextraweightsum' || $coefstring == 'aggregationcoefextraweight') { $this->uses_weight = true; } foreach ($element['children'] as $child_el) { if ($level > $deepest_level) { $deepest_level = $level; } $deepest_level = $this->get_deepest_level($child_el, $level, $deepest_level); } $category = grade_category::fetch(array('id' => $object->id)); $item = $category->get_grade_item(); if ($item->gradetype == GRADE_TYPE_NONE) { // Add 1 more level for grade category that has no total. $deepest_level++; } } return $deepest_level; }
function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; $somecat = new grade_category(); foreach ($somecat->forceable as $property) { if ((int) $CFG->{"grade_{$property}_flag"} & 1) { if ($mform->elementExists($property)) { if (empty($CFG->grade_hideforcedsettings)) { $mform->hardFreeze($property); } else { if ($mform->elementExists($property)) { $mform->removeElement($property); } } } } } if ($CFG->grade_droplow > 0) { if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } } else { if ($CFG->grade_keephigh > 0) { if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } } } if ($id = $mform->getElementValue('id')) { $grade_category = grade_category::fetch(array('id' => $id)); $grade_item = $grade_category->load_grade_item(); // remove agg coef if not used if ($grade_category->is_course_category()) { if ($mform->elementExists('parentcategory')) { $mform->removeElement('parentcategory'); } if ($mform->elementExists('currentparentaggregation')) { $mform->removeElement('currentparentaggregation'); } } else { // if we wanted to change parent of existing category - we would have to verify there are no circular references in parents!!! if ($mform->elementExists('parentcategory')) { $mform->hardFreeze('parentcategory'); } $parent_cat = $grade_category->get_parent_category(); $mform->setDefault('currentparentaggregation', $this->aggregation_options[$parent_cat->aggregation]); } if ($grade_item->is_calculated()) { // following elements are ignored when calculation formula used if ($mform->elementExists('aggregation')) { $mform->removeElement('aggregation'); } if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } if ($mform->elementExists('aggregateonlygraded')) { $mform->removeElement('aggregateonlygraded'); } if ($mform->elementExists('aggregateoutcomes')) { $mform->removeElement('aggregateoutcomes'); } if ($mform->elementExists('aggregatesubcats')) { $mform->removeElement('aggregatesubcats'); } } // If it is a course category, remove the "required" rule from the "fullname" element if ($grade_category->is_course_category()) { unset($mform->_rules['fullname']); $key = array_search('fullname', $mform->_required); unset($mform->_required[$key]); } // If it is a course category and its fullname is ?, show an empty field if ($grade_category->is_course_category() && $mform->getElementValue('fullname') == '?') { $mform->setDefault('fullname', ''); } // remove unwanted aggregation options if ($mform->elementExists('aggregation')) { $allaggoptions = array_keys($this->aggregation_options); $agg_el =& $mform->getElement('aggregation'); $visible = explode(',', $CFG->grade_aggregations_visible); if (!is_null($grade_category->aggregation)) { // current type is always visible $visible[] = $grade_category->aggregation; } foreach ($allaggoptions as $type) { if (!in_array($type, $visible)) { $agg_el->removeOption($type); } } } } else { // adding new category if ($mform->elementExists('currentparentaggregation')) { $mform->removeElement('currentparentaggregation'); } // remove unwanted aggregation options if ($mform->elementExists('aggregation')) { $allaggoptions = array_keys($this->aggregation_options); $agg_el =& $mform->getElement('aggregation'); $visible = explode(',', $CFG->grade_aggregations_visible); foreach ($allaggoptions as $type) { if (!in_array($type, $visible)) { $agg_el->removeOption($type); } } } } // no parent header for course category if (!$mform->elementExists('parentcategory')) { $mform->removeElement('headerparent'); } /// GRADE ITEM if ($id = $mform->getElementValue('id')) { $grade_category = grade_category::fetch(array('id' => $id)); $grade_item = $grade_category->load_grade_item(); $mform->setDefault('grade_item_hidden', (int) $grade_item->hidden); if ($grade_item->is_outcome_item()) { // we have to prevent incompatible modifications of outcomes if outcomes disabled $mform->removeElement('grade_item_grademax'); $mform->removeElement('grade_item_grademin'); $mform->removeElement('grade_item_gradetype'); $mform->removeElement('grade_item_display'); $mform->removeElement('grade_item_decimals'); $mform->hardFreeze('grade_item_scaleid'); } //remove the aggregation coef element if not needed if ($grade_item->is_course_item()) { if ($mform->elementExists('grade_item_aggregationcoef')) { $mform->removeElement('grade_item_aggregationcoef'); } } else { if ($grade_item->is_category_item()) { $category = $grade_item->get_item_category(); $parent_category = $category->get_parent_category(); } else { $parent_category = $grade_item->get_parent_category(); } $parent_category->apply_forced_settings(); if (!$parent_category->is_aggregationcoef_used()) { if ($mform->elementExists('grade_item_aggregationcoef')) { $mform->removeElement('grade_item_aggregationcoef'); } } else { $coefstring = $grade_item->get_coefstring(); if ($coefstring == 'aggregationcoefextrasum') { // advcheckbox is not compatible with disabledIf! $element =& $mform->createElement('checkbox', 'grade_item_aggregationcoef', get_string($coefstring, 'grades')); } else { $element =& $mform->createElement('text', 'grade_item_aggregationcoef', get_string($coefstring, 'grades')); } $mform->insertElementBefore($element, 'parentcategory'); $mform->addHelpButton('grade_item_aggregationcoef', $coefstring, 'grades'); } } } }
$PAGE->set_pagelayout('admin'); /// Make sure they can even access this course if (!($course = $DB->get_record('course', array('id' => $courseid)))) { print_error('nocourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); // todo $PAGE->requires->js_module() should be used here instead $PAGE->requires->js('/grade/edit/tree/functions.js'); /// return tracking object $gpr = new grade_plugin_return(array('type' => 'edit', 'plugin' => 'tree', 'courseid' => $courseid)); $returnurl = $gpr->get_return_url(null); // Change category aggregation if requested if (!is_null($category) && !is_null($aggregationtype) && confirm_sesskey()) { if (!($grade_category = grade_category::fetch(array('id' => $category, 'courseid' => $courseid)))) { print_error('invalidcategoryid'); } $data = new stdClass(); $data->aggregation = $aggregationtype; grade_category::set_properties($grade_category, $data); $grade_category->update(); grade_regrade_final_grades($courseid); } //first make sure we have proper final grades - we need it for locking changes $normalisationmessage = null; $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid); grade_regrade_final_grades($courseid); $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid); if (array_diff($originalweights, $alteredweights)) { $normalisationmessage = get_string('weightsadjusted', 'grades');
function test_gradebook() { global $DB; $this->resetAfterTest(true); // reset all changes automatically after this test $location_str = 'manual'; // try to get category $grade_category = grade_category::fetch(array('courseid' => $this->courseid, 'fullname' => $this->cat_name)); // NOTE: grade category will not be null but it will be empty $this->assertFalse($grade_category); // create a category $params = new stdClass(); $params->courseid = $this->courseid; $params->fullname = $this->cat_name; $grade_category = new grade_category($params, false); $this->assertTrue(method_exists($grade_category, 'insert')); $grade_category->insert($location_str); // now we will really get the category that we just made $grade_category_fetched = grade_category::fetch(array('courseid' => $this->courseid, 'fullname' => $this->cat_name)); $this->assertTrue($grade_category_fetched !== false); $this->assertEquals($grade_category->id, $grade_category_fetched->id); $this->assertEquals($grade_category->courseid, $grade_category_fetched->courseid); $this->assertEquals($grade_category->path, $grade_category_fetched->path); $this->assertEquals($grade_category->fullname, $grade_category_fetched->fullname); $this->assertEquals($grade_category->parent, $grade_category_fetched->parent); // try to get grade item $grade_item = grade_item::fetch(array('courseid' => $this->courseid, 'categoryid' => $grade_category->id, 'itemname' => $this->item_name)); // NOTE: grade category will not be null but it will be empty $this->assertFalse($grade_item); // create a grade item $grade_item = new grade_item(); $this->assertTrue(method_exists($grade_item, 'insert')); $grade_item->courseid = $this->courseid; $grade_item->categoryid = $grade_category->id; $grade_item->idnumber = $this->item_name; // lookup $grade_item->itemname = $this->item_name; // display $grade_item->itemtype = 'blocks'; $grade_item->itemmodule = 'iclicker'; $grade_item->iteminfo = 'blocks/iclicker for unit testing'; // grademax=100, grademin=0 $grade_item->grademax = 100.0; $grade_item->insert($location_str); // now we will really get the new item $grade_item_fetched = grade_item::fetch(array('courseid' => $this->courseid, 'categoryid' => $grade_category->id, 'itemname' => $this->item_name)); $this->assertTrue($grade_item_fetched !== false); $this->assertEquals($grade_item->id, $grade_item_fetched->id); $this->assertEquals($grade_item->courseid, $grade_item_fetched->courseid); $this->assertEquals($grade_item->categoryid, $grade_item_fetched->categoryid); $this->assertEquals($grade_item->itemname, $grade_item_fetched->itemname); // get empty grades list $all_grades = grade_grade::fetch_all(array('itemid' => $grade_item->id)); $this->assertFalse($all_grades); // add grade $grade_grade = new grade_grade(); $this->assertTrue(method_exists($grade_grade, 'insert')); $grade_grade->itemid = $grade_item->id; $grade_grade->userid = $this->studentid1; $grade_grade->rawgrade = $this->grade_score; $grade_grade->insert($location_str); // get new grade $grade_grade_fetched = grade_grade::fetch(array('itemid' => $grade_item->id, 'userid' => $this->studentid1)); $this->assertTrue($grade_grade_fetched !== false); $this->assertEquals($grade_grade->id, $grade_grade_fetched->id); $this->assertEquals($grade_grade->itemid, $grade_grade_fetched->itemid); $this->assertEquals($grade_grade->userid, $grade_grade_fetched->userid); $this->assertEquals($grade_grade->rawgrade, $grade_grade_fetched->rawgrade); // update the grade $grade_grade->rawgrade = 50; $result = $grade_grade->update($location_str); $this->assertTrue($result); $grade_grade_fetched = grade_grade::fetch(array('id' => $grade_grade->id)); $this->assertTrue($grade_grade_fetched !== false); $this->assertEquals($grade_grade->id, $grade_grade_fetched->id); $this->assertEquals($grade_grade->rawgrade, $grade_grade_fetched->rawgrade); $this->assertEquals(50, $grade_grade_fetched->rawgrade); // get grades $all_grades = grade_grade::fetch_all(array('itemid' => $grade_item->id)); $this->assertTrue($all_grades !== false); $this->assertEquals(1, sizeof($all_grades)); // add more grades $grade_grade2 = new grade_grade(); $grade_grade2->itemid = $grade_item->id; $grade_grade2->userid = $this->studentid2; $grade_grade2->rawgrade = $this->grade_score; $grade_grade2->insert($location_str); // get grades $all_grades = grade_grade::fetch_all(array('itemid' => $grade_item->id)); $this->assertTrue($all_grades !== false); $this->assertEquals(2, sizeof($all_grades)); // make sure this can run $result = $grade_item->regrade_final_grades(); $this->assertTrue($result); // remove grades $this->assertTrue(method_exists($grade_grade, 'delete')); $result = $grade_grade->delete($location_str); $this->assertTrue($result); $result = $grade_grade2->delete($location_str); $this->assertTrue($result); // check no grades left $all_grades = grade_grade::fetch_all(array('itemid' => $grade_item->id)); $this->assertFalse($all_grades); // remove grade item $this->assertTrue(method_exists($grade_item, 'delete')); $result = $grade_item->delete($location_str); $this->assertTrue($result); // remove grade category $this->assertTrue(method_exists($grade_category, 'delete')); $result = $grade_category->delete($location_str); $this->assertTrue($result); $this->resetAfterTest(); }