MDL-10579 more capability checks in grades code + refactoring of grade_tree

This commit is contained in:
skodak 2007-07-24 07:45:15 +00:00
parent 5d71ece008
commit 7a6b7acf76
13 changed files with 445 additions and 378 deletions

72
grade/edit/action.php Normal file
View File

@ -0,0 +1,72 @@
<?php // $Id$
require_once '../../config.php';
require_once $CFG->dirroot.'/grade/lib.php';
$courseid = required_param('id', PARAM_INT);
$action = required_param('action', PARAM_ALPHA);
$eid = required_param('eid', PARAM_ALPHANUM);
/// Make sure they can even access this course
if (!$course = get_record('course', 'id', $courseid)) {
print_error('nocourseid');
}
require_login($course);
$context = get_context_instance(CONTEXT_COURSE, $course->id);
// default return url
$gpr = new grade_plugin_return();
$returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/edit/tree.php?id='.$course->id);
// get the grading tree object
$gtree = new grade_tree($courseid, false, false);
// what are we working with?
if (!$element = $gtree->locate_element($eid)) {
error('Incorrect element id!', $returnurl);
}
$object = $element['object'];
switch ($action) {
case 'hide':
if ($eid and confirm_sesskey()) {
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
error('No permission to hide!', $returnurl);
}
$object->set_hidden(1);
}
break;
case 'show':
if ($eid and confirm_sesskey()) {
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
error('No permission to show!', $returnurl);
}
$object->set_hidden(0);
}
break;
case 'lock':
if ($eid and confirm_sesskey()) {
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context)) {
error('No permission to lock!', $returnurl);
}
$object->set_locked(1);
}
break;
case 'unlock':
if ($eid and confirm_sesskey()) {
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context)) {
error('No permission to unlock!', $returnurl);
}
$object->set_locked(0);
}
break;
}
redirect($returnurl);
//redirect($returnurl, 'debug delay', 5);
?>

View File

@ -1,7 +1,7 @@
<?php //$Id$
require_once '../../config.php';
require_once $CFG->dirroot.'/grade/lib.php';
require_once $CFG->libdir.'/gradelib.php';
require_once 'calculation_form.php';
$courseid = required_param('courseid', PARAM_INT);

View File

@ -3,7 +3,6 @@
require_once '../../config.php';
require_once $CFG->dirroot.'/grade/lib.php';
require_once $CFG->dirroot.'/grade/report/lib.php';
require_once $CFG->libdir.'/gradelib.php';
require_once 'category_form.php';
$courseid = required_param('courseid', PARAM_INT);

View File

@ -2,7 +2,6 @@
require_once '../../config.php';
require_once $CFG->dirroot.'/grade/lib.php';
require_once $CFG->libdir.'/gradelib.php';
require_once 'grade_form.php';
$courseid = required_param('courseid', PARAM_INT);

View File

@ -1,8 +1,8 @@
<?php //$Id$
require_once '../../config.php';
require_once $CFG->dirroot.'/grade/lib.php';
require_once $CFG->dirroot.'/grade/report/lib.php';
require_once $CFG->libdir.'/gradelib.php';
require_once 'item_form.php';
$courseid = required_param('courseid', PARAM_INT);

View File

@ -1,5 +1,4 @@
<?php
// $Id$
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
@ -26,7 +25,6 @@
require_once '../../config.php';
require_once $CFG->dirroot.'/grade/lib.php';
require_once $CFG->libdir.'/gradelib.php';
$courseid = required_param('id', PARAM_INT);
$action = optional_param('action', 0, PARAM_ALPHA);
@ -40,12 +38,15 @@ if (!$course = get_record('course', 'id', $courseid)) {
}
require_login($course);
$context = get_context_instance(CONTEXT_COURSE, $course->id);
//require_capability() here!!
require_capability('moodle/grade:manage', $context);
// default return url
$returnurl = 'tree.php?id='.$course->id;
/// return tracking object
$gpr = new grade_plugin_return(array('type'=>'edit', 'courseid'=>$courseid));
$returnurl = $gpr->get_return_url(null);
//first make sure we have proper final grades - we need it for locking changes
grade_regrade_final_grades($courseid);
// get the grading tree object
// note: total must be first for moving to work correctly, if you want it last moving code must be rewritten!
@ -59,7 +60,7 @@ if (empty($eid)) {
if (!$element = $gtree->locate_element($eid)) {
error('Incorrect element id!', $returnurl);
}
$object = $element['object'];
$object = $element['object'];
}
@ -74,16 +75,6 @@ $navigation = build_navigation($nav);
$moving = false;
switch ($action) {
case 'edit':
if ($eid and confirm_sesskey()) {
if ($element['type'] == 'category') {
redirect('category.php?courseid='.$course->id.'&amp;id='.$object->id);
} else {
redirect('item.php?courseid='.$course->id.'&amp;id='.$object->id);
}
}
break;
case 'delete':
if ($eid) {
$confirm = optional_param('confirm', 0, PARAM_BOOL);
@ -135,35 +126,6 @@ switch ($action) {
}
break;
case 'hide':
if ($eid and confirm_sesskey()) {
$object->set_hidden(1);
redirect($returnurl);
}
break;
case 'show':
if ($eid and confirm_sesskey()) {
$object->set_hidden(0);
redirect($returnurl);
}
break;
case 'lock':
if ($eid and confirm_sesskey()) {
//TODO: add error handling in redirect
$object->set_locked(1);
redirect($returnurl);
}
break;
case 'unlock':
if ($eid and confirm_sesskey()) {
$object->set_locked(0);
redirect($returnurl);
}
break;
default:
break;
}
@ -178,7 +140,7 @@ print_heading(get_string('categoriesedit', 'grades'));
print_box_start('gradetreebox generalbox');
echo '<ul id="grade_tree">';
print_grade_tree($gtree->top_element, $moving);
print_grade_tree($gtree, $gtree->top_element, $moving, $gpr);
echo '</ul>';
print_box_end();
@ -198,43 +160,32 @@ die;
function print_grade_tree($element, $moving) {
function print_grade_tree(&$gtree, $element, $moving, &$gpr) {
global $CFG, $COURSE;
/// fetch needed strings
$strmove = get_string('move');
$strmovehere = get_string('movehere');
$stredit = get_string('edit');
$strdelete = get_string('delete');
$strhide = get_string('hide');
$strshow = get_string('show');
$strlock = get_string('lock', 'grades');
$strunlock = get_string('unlock', 'grades');
$object = $element['object'];
$eid = $element['eid'];
/// prepare actions
$actions = '<a href="tree.php?id='.$COURSE->id.'&amp;action=edit&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$stredit.'" title="'.$stredit.'"/></a>';
$actions = $gtree->get_edit_icon($element, $gpr);
if ($element['type'] == 'item' or ($element['type'] == 'category' and $element['depth'] > 1)) {
$actions .= '<a href="tree.php?id='.$COURSE->id.'&amp;action=delete&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.$strdelete.'" title="'.$strdelete.'"/></a>';
$actions .= '<a href="tree.php?id='.$COURSE->id.'&amp;action=moveselect&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/move.gif" class="iconsmall" alt="'.$strmove.'" title="'.$strmove.'"/></a>';
}
if ($object->is_locked()) {
$actions .= '<a href="tree.php?id='.$COURSE->id.'&amp;action=unlock&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/unlock.gif" class="iconsmall" alt="'.$strunlock.'" title="'.$strunlock.'"/></a>';
} else {
$actions .= '<a href="tree.php?id='.$COURSE->id.'&amp;action=lock&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/lock.gif" class="iconsmall" alt="'.$strlock.'" title="'.$strlock.'"/></a>';
}
$actions .= $gtree->get_locking_icon($element, $gpr);
$name = $object->get_name();
if ($object->is_hidden()) {
$name = '<span class="dimmed_text">'.$object->get_name().'</span>';
$actions .= '<a href="tree.php?id='.$COURSE->id.'&amp;action=show&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.$strshow.'" title="'.$strshow.'"/></a>';
} else {
$name = $object->get_name();
$actions .= '<a href="tree.php?id='.$COURSE->id.'&amp;action=hide&amp;eid='.$eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.$strhide.'" title="'.$strhide.'"/></a>';
$name = '<span class="dimmed_text">'.$name.'</span>';
}
$actions .= $gtree->get_hiding_icon($element, $gpr);
/// prepare icon
$icon = '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="icon" alt=""/>';
@ -275,7 +226,7 @@ function print_grade_tree($element, $moving) {
echo '<li class="'.$element['type'].'">'.$icon.$name.$actions;
echo '<ul class="catlevel'.$element['depth'].'">';
foreach($element['children'] as $child_el) {
print_grade_tree($child_el, $moving);
print_grade_tree($gtree, $child_el, $moving, $gpr);
}
echo '</ul></li>';
if ($element['depth'] > 1) {

View File

@ -1,5 +1,7 @@
<?php //$Id$
require_once $CFG->libdir.'/gradelib.php';
/**
* Print grading plugin selection popup form.
*
@ -91,7 +93,7 @@ function print_grade_plugin_selector($courseid, $active_type, $active_plugin, $r
}
/// editing scripts - not real plugins
if (true) { //TODO: add proper capability here
if (has_capability('moodle/grade:manage', $context)) { //TODO: add proper capability here
$menu['edit']='--'.get_string('edit');
$url = 'edit/tree.php?id='.$courseid;
if ($active_type == 'edit' and $active_plugin == 'tree' ) {
@ -105,7 +107,7 @@ function print_grade_plugin_selector($courseid, $active_type, $active_plugin, $r
}
/**
* Utility class used for return tracking when using edit and other forms from grade plubins
* Utility class used for return tracking when using edit and other forms in grade plugins
*/
class grade_plugin_return {
var $type;
@ -140,13 +142,15 @@ class grade_plugin_return {
* @return array options
*/
function get_options() {
if (empty($this->type) or empty($this->plugin)) {
if (empty($this->type)) {
return array();
}
$params = array();
$params['plugin'] = $this->plugin;
if (!empty($this->plugin)) {
$params['plugin'] = $this->plugin;
}
if (!empty($this->courseid)) {
$params['id'] = $this->courseid;
@ -171,6 +175,10 @@ class grade_plugin_return {
function get_return_url($default, $extras=null) {
global $CFG;
if ($this->type == 'edit') {
return $CFG->wwwroot.'/grade/edit/tree.php?id='.$this->courseid;
}
if (empty($this->type) or empty($this->plugin)) {
return $default;
}
@ -197,7 +205,7 @@ class grade_plugin_return {
foreach($extras as $key=>$value) {
$url .= $glue.$key.'='.$value;
$glue = '&amp;';
}
}
}
return $url;
@ -208,12 +216,15 @@ class grade_plugin_return {
* @return string
*/
function get_form_fields() {
if (empty($this->type) or empty($this->plugin)) {
if (empty($this->type)) {
return '';
}
$result = '<input type="hidden" name="gpr_type" value="'.$this->type.'" />';
$result .= '<input type="hidden" name="gpr_plugin" value="'.$this->plugin.'" />';
if (!empty($this->plugin)) {
$result .= '<input type="hidden" name="gpr_plugin" value="'.$this->plugin.'" />';
}
if (!empty($this->courseid)) {
$result .= '<input type="hidden" name="gpr_courseid" value="'.$this->courseid.'" />';
@ -234,15 +245,17 @@ class grade_plugin_return {
* @return void
*/
function add_mform_elements(&$mform) {
if (empty($this->type) or empty($this->plugin)) {
if (empty($this->type)) {
return;
}
$mform->addElement('hidden', 'gpr_type', $this->type);
$mform->setType('gpr_type', PARAM_SAFEDIR);
$mform->addElement('hidden', 'gpr_plugin', $this->plugin);
$mform->setType('gpr_plugin', PARAM_SAFEDIR);
if (!empty($this->plugin)) {
$mform->addElement('hidden', 'gpr_plugin', $this->plugin);
$mform->setType('gpr_plugin', PARAM_SAFEDIR);
}
if (!empty($this->courseid)) {
$mform->addElement('hidden', 'gpr_courseid', $this->courseid);
@ -266,7 +279,7 @@ class grade_plugin_return {
* @return string $url with erturn tracking params
*/
function add_url_params($url) {
if (empty($this->type) or empty($this->plugin)) {
if (empty($this->type)) {
return $url;
}
@ -276,7 +289,9 @@ class grade_plugin_return {
$url .= '&amp;gpr_type='.$this->type;
}
$url .= '&amp;gpr_plugin='.$this->plugin;
if (!empty($this->plugin)) {
$url .= '&amp;gpr_plugin='.$this->plugin;
}
if (!empty($this->courseid)) {
$url .= '&amp;gpr_courseid='.$this->courseid;
@ -293,4 +308,324 @@ class grade_plugin_return {
return $url;
}
}
/**
* This class represents a complete tree of categories, grade_items and final grades,
* organises as an array primarily, but which can also be converted to other formats.
* It has simple method calls with complex implementations, allowing for easy insertion,
* deletion and moving of items and categories within the tree.
*/
class grade_tree {
/**
* The basic representation of the tree as a hierarchical, 3-tiered array.
* @var object $top_element
*/
var $top_element;
/**
* A string of GET URL variables, namely courseid and sesskey, used in most URLs built by this class.
* @var string $commonvars
*/
var $commonvars;
/**
* 2D array of grade items and categories
*/
var $levels;
/**
* Constructor, retrieves and stores a hierarchical array of all grade_category and grade_item
* objects for the given courseid. Full objects are instantiated.
* and renumbering.
* @param int $courseid
* @param boolean $fillers include fillers and colspans, make the levels var "rectangular"
* @param boolean $category_grade_last category grade item is the last child
* @param boolean $aggregation_view Either full view (0) or compact view (1)
*/
function grade_tree($courseid, $fillers=true, $category_grade_last=false,
$aggregation_view=GRADE_REPORT_AGGREGATION_VIEW_FULL) {
global $USER, $CFG;
$this->courseid = $courseid;
$this->commonvars = "&amp;sesskey=$USER->sesskey&amp;id=$this->courseid";
$this->levels = array();
// get course grade tree
$this->top_element = grade_category::fetch_course_tree($courseid, true);
if ($category_grade_last) {
grade_tree::category_grade_last($this->top_element);
}
if ($fillers) {
// inject fake categories == fillers
grade_tree::inject_fillers($this->top_element, 0);
// add colspans to categories and fillers
grade_tree::inject_colspans($this->top_element);
}
grade_tree::fill_levels($this->levels, $this->top_element, 0);
}
/**
* Static recursive helper - makes the grade_item for category the last children
* @static
* @param array $element The seed of the recursion
* @return void
*/
function category_grade_last(&$element) {
if (empty($element['children'])) {
return;
}
if (count($element['children']) < 2) {
return;
}
$category_item = reset($element['children']);
$order = key($element['children']);
unset($element['children'][$order]);
$element['children'][$order] =& $category_item;
foreach ($element['children'] as $sortorder=>$child) {
grade_tree::category_grade_last($element['children'][$sortorder]);
}
}
/**
* Static recursive helper - fills the levels array, useful when accessing tree elements of one level
* @static
* @param int $levels
* @param array $element The seed of the recursion
* @param int $depth
* @return void
*/
function fill_levels(&$levels, &$element, $depth) {
if (!array_key_exists($depth, $levels)) {
$levels[$depth] = array();
}
// prepare unique identifier
if ($element['type'] == 'category') {
$element['eid'] = 'c'.$element['object']->id;
} else if (in_array($element['type'], array('item', 'courseitem', 'categoryitem'))) {
$element['eid'] = 'i'.$element['object']->id;
}
$levels[$depth][] =& $element;
$depth++;
if (empty($element['children'])) {
return;
}
$prev = 0;
foreach ($element['children'] as $sortorder=>$child) {
grade_tree::fill_levels($levels, $element['children'][$sortorder], $depth);
$element['children'][$sortorder]['prev'] = $prev;
$element['children'][$sortorder]['next'] = 0;
if ($prev) {
$element['children'][$prev]['next'] = $sortorder;
}
$prev = $sortorder;
}
}
/**
* Static recursive helper - makes full tree (all leafes are at the same level)
*/
function inject_fillers(&$element, $depth) {
$depth++;
if (empty($element['children'])) {
return $depth;
}
$chdepths = array();
$chids = array_keys($element['children']);
$last_child = end($chids);
$first_child = reset($chids);
foreach ($chids as $chid) {
$chdepths[$chid] = grade_tree::inject_fillers($element['children'][$chid], $depth);
}
arsort($chdepths);
$maxdepth = reset($chdepths);
foreach ($chdepths as $chid=>$chd) {
if ($chd == $maxdepth) {
continue;
}
for ($i=0; $i < $maxdepth-$chd; $i++) {
if ($chid == $first_child) {
$type = 'fillerfirst';
} else if ($chid == $last_child) {
$type = 'fillerlast';
} else {
$type = 'filler';
}
$oldchild =& $element['children'][$chid];
$element['children'][$chid] = array('object'=>'filler', 'type'=>$type, 'eid'=>'', 'depth'=>$element['object']->depth,'children'=>array($oldchild));
}
}
return $maxdepth;
}
/**
* Static recursive helper - add colspan information into categories
*/
function inject_colspans(&$element) {
if (empty($element['children'])) {
return 1;
}
$count = 0;
foreach ($element['children'] as $key=>$child) {
$count += grade_tree::inject_colspans($element['children'][$key]);
}
$element['colspan'] = $count;
return $count;
}
/**
* Parses the array in search of a given eid and returns a element object with
* information about the element it has found.
* @param int $eid
* @return object element
*/
function locate_element($eid) {
if (strpos($eid, 'g') === 0) {
// it is a grade construct a new object
$id = (int)substr($eid, 1);
if (!$grade = grade_grade::fetch(array('id'=>$id))) {
return null;
}
//extra security check - the grade item must be in this tree
if (!$item_el = $this->locate_element('i'.$grade->itemid)) {
return null;
}
$grade->grade_item =& $item_el['object']; // this may speedup grade_grade methods!
return array('eid'=>'g'.$id,'object'=>$grade, 'type'=>'grade');
}
// it is a category or item
foreach ($this->levels as $row) {
foreach ($row as $element) {
if ($element['type'] == 'filler') {
continue;
}
if ($element['eid'] == $eid) {
return $element;
}
}
}
return null;
}
/**
* Return edit icon for give element
* @param object $element
* @return string
*/
function get_edit_icon($element, $gpr) {
global $CFG;
$context = get_context_instance(CONTEXT_COURSE, $this->courseid);
if (!has_capability('moodle/grade:manage', $context)) {
return '';
}
$object = $element['object'];
switch ($element['type']) {
case 'item':
case 'categoryitem':
case 'courseitem':
$url = $CFG->wwwroot.'/grade/edit/item.php?courseid='.$this->courseid.'&amp;id='.$object->id;
$url = $gpr->add_url_params($url);
break;
case 'category':
$url = $CFG->wwwroot.'/grade/edit/category.php?courseid='.$this->courseid.'&amp;id='.$object->id;
$url = $gpr->add_url_params($url);
break;
case 'grade':
//TODO: improve dealing with new grades
$url = $CFG->wwwroot.'/grade/edit/grade.php?courseid='.$this->courseid.'&amp;id='.$object->id;
$url = $gpr->add_url_params($url);
break;
default:
$url = null;
}
if ($url) {
$stredit = get_string('edit');
return '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'.$stredit.'" title="'.$stredit.'"/></a>';
} else {
return '';
}
}
/**
* Return hiding icon for give element
* @param object $element
* @return string
*/
function get_hiding_icon($element, $gpr) {
global $CFG;
$context = get_context_instance(CONTEXT_COURSE, $this->courseid);
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
return '';
}
if ($element['object']->is_hidden()) {
$strshow = get_string('show');
$url = $CFG->wwwroot.'/grade/edit/action.php?id='.$this->courseid.'&amp;action=show&amp;sesskey='.sesskey().'&amp;eid='.$element['eid'];
$url = $gpr->add_url_params($url);
$action = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.$strshow.'" title="'.$strshow.'"/></a>';
} else {
$strhide = get_string('hide');
$url = $CFG->wwwroot.'/grade/edit/action.php?id='.$this->courseid.'&amp;action=hide&amp;sesskey='.sesskey().'&amp;eid='.$element['eid'];
$url = $gpr->add_url_params($url);
$action = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.$strhide.'" title="'.$strhide.'"/></a>';
}
return $action;
}
/**
* Return locking icon for give element
* @param object $element
* @return string
*/
function get_locking_icon($element, $gpr) {
global $CFG;
$context = get_context_instance(CONTEXT_COURSE, $this->courseid);
if ($element['object']->is_locked()) {
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context)) {
return '';
}
$strunlock = get_string('unlock', 'grades');
$url = $CFG->wwwroot.'/grade/edit/action.php?id='.$this->courseid.'&amp;action=unlock&amp;sesskey='.sesskey().'&amp;eid='.$element['eid'];
$url = $gpr->add_url_params($url);
$action = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/unlock.gif" class="iconsmall" alt="'.$strunlock.'" title="'.$strunlock.'"/></a>';
} else {
if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context)) {
return '';
}
$strlock = get_string('lock', 'grades');
$url = $CFG->wwwroot.'/grade/edit/action.php?id='.$this->courseid.'&amp;action=lock&amp;sesskey='.sesskey().'&amp;eid='.$element['eid'];
$url = $gpr->add_url_params($url);
$action = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/lock.gif" class="iconsmall" alt="'.$strlock.'" title="'.$strlock.'"/></a>';
}
return $action;
}
}
?>

View File

@ -127,7 +127,7 @@ $numusers = $report->get_numusers();
$report->load_final_grades();
/// Print header
print_header_simple($strgrades.':'.$reportname, ':'.$strgrades, $navigation,
print_header_simple($strgrades.': '.$reportname, ': '.$strgrades, $navigation,
'', '', true, $buttons, navmenu($course));
/// Print the plugin selector at the top

View File

@ -66,7 +66,7 @@ if (empty($last)) {
} else if (in_array('user', $reports)) {
$last = 'user';
} else {
$last = reset($reports);
}

View File

@ -53,7 +53,7 @@ if (has_capability('moodle/grade:viewall', $context)) {
} else if (has_capability('moodle/grade:view', $usercontext) and $course->showgrades) {
// ok - can view grades of this user- parent most probably
} else {
$acces = false;
}
@ -77,7 +77,7 @@ $navigation = build_navigation($navlinks);
/// Print header
print_header_simple($strgrades.':'.$reportname, ':'.$strgrades, $navigation,
print_header_simple($strgrades.': '.$reportname, ': '.$strgrades, $navigation,
'', '', true, '', navmenu($course));
/// Print the plugin selector at the top
@ -90,13 +90,13 @@ if ($access) {
// Create a report instance
$report = new grade_report_user($courseid, $gpr, $context, $userid);
$gradetotal = 0;
$gradesum = 0;
// print the page
print_heading(get_string('modulename', 'gradereport_user'). ' - '.fullname($report->user));
if ($report->fill_table()) {
echo $report->print_table(true);
}

View File

@ -1,238 +0,0 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-2003 Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
require_once $CFG->libdir . '/gradelib.php';
/**
* This class represents a complete tree of categories, grade_items and final grades,
* organises as an array primarily, but which can also be converted to other formats.
* It has simple method calls with complex implementations, allowing for easy insertion,
* deletion and moving of items and categories within the tree.
*/
class grade_tree {
/**
* The basic representation of the tree as a hierarchical, 3-tiered array.
* @var object $top_element
*/
var $top_element;
/**
* A string of GET URL variables, namely courseid and sesskey, used in most URLs built by this class.
* @var string $commonvars
*/
var $commonvars;
/**
* 2D array of grade items and categories
*/
var $levels;
/**
* Constructor, retrieves and stores a hierarchical array of all grade_category and grade_item
* objects for the given courseid. Full objects are instantiated.
* and renumbering.
* @param int $courseid
* @param boolean $fillers include fillers and colspans, make the levels var "rectangular"
* @param boolean $category_grade_last category grade item is the last child
* @param boolean $aggregation_view Either full view (0) or compact view (1)
*/
function grade_tree($courseid, $fillers=true, $category_grade_last=false,
$aggregation_view=GRADE_REPORT_AGGREGATION_VIEW_FULL) {
global $USER;
$this->courseid = $courseid;
$this->commonvars = "&amp;sesskey=$USER->sesskey&amp;id=$this->courseid";
$this->levels = array();
// get course grade tree
$this->top_element = grade_category::fetch_course_tree($courseid, true);
if ($category_grade_last) {
grade_tree::category_grade_last($this->top_element);
}
if ($fillers) {
// inject fake categories == fillers
grade_tree::inject_fillers($this->top_element, 0);
// add colspans to categories and fillers
grade_tree::inject_colspans($this->top_element);
}
grade_tree::fill_levels($this->levels, $this->top_element, 0);
}
/**
* Static recursive helper - makes the grade_item for category the last children
* @static
* @param array $element The seed of the recursion
* @return void
*/
function category_grade_last(&$element) {
if (empty($element['children'])) {
return;
}
if (count($element['children']) < 2) {
return;
}
$category_item = reset($element['children']);
$order = key($element['children']);
unset($element['children'][$order]);
$element['children'][$order] =& $category_item;
foreach ($element['children'] as $sortorder=>$child) {
grade_tree::category_grade_last($element['children'][$sortorder]);
}
}
/**
* Static recursive helper - fills the levels array, useful when accessing tree elements of one level
* @static
* @param int $levels
* @param array $element The seed of the recursion
* @param int $depth
* @return void
*/
function fill_levels(&$levels, &$element, $depth) {
if (!array_key_exists($depth, $levels)) {
$levels[$depth] = array();
}
// prepare unique identifier
if ($element['type'] == 'category') {
$element['eid'] = 'c'.$element['object']->id;
} else if (in_array($element['type'], array('item', 'courseitem', 'categoryitem'))) {
$element['eid'] = 'i'.$element['object']->id;
}
$levels[$depth][] =& $element;
$depth++;
if (empty($element['children'])) {
return;
}
$prev = 0;
foreach ($element['children'] as $sortorder=>$child) {
grade_tree::fill_levels($levels, $element['children'][$sortorder], $depth);
$element['children'][$sortorder]['prev'] = $prev;
$element['children'][$sortorder]['next'] = 0;
if ($prev) {
$element['children'][$prev]['next'] = $sortorder;
}
$prev = $sortorder;
}
}
/**
* Static recursive helper - makes full tree (all leafes are at the same level)
*/
function inject_fillers(&$element, $depth) {
$depth++;
if (empty($element['children'])) {
return $depth;
}
$chdepths = array();
$chids = array_keys($element['children']);
$last_child = end($chids);
$first_child = reset($chids);
foreach ($chids as $chid) {
$chdepths[$chid] = grade_tree::inject_fillers($element['children'][$chid], $depth);
}
arsort($chdepths);
$maxdepth = reset($chdepths);
foreach ($chdepths as $chid=>$chd) {
if ($chd == $maxdepth) {
continue;
}
for ($i=0; $i < $maxdepth-$chd; $i++) {
if ($chid == $first_child) {
$type = 'fillerfirst';
} else if ($chid == $last_child) {
$type = 'fillerlast';
} else {
$type = 'filler';
}
$oldchild =& $element['children'][$chid];
$element['children'][$chid] = array('object'=>'filler', 'type'=>$type, 'eid'=>'', 'depth'=>$element['object']->depth,'children'=>array($oldchild));
}
}
return $maxdepth;
}
/**
* Static recursive helper - add colspan information into categories
*/
function inject_colspans(&$element) {
if (empty($element['children'])) {
return 1;
}
$count = 0;
foreach ($element['children'] as $key=>$child) {
$count += grade_tree::inject_colspans($element['children'][$key]);
}
$element['colspan'] = $count;
return $count;
}
/**
* Parses the array in search of a given eid and returns a element object with
* information about the element it has found.
* @param int $eid
* @return object element
*/
function locate_element($eid) {
if (strpos($eid, 'g') === 0) {
// it is a grade construct a new object
$id = (int)substr($eid, 1);
if (!$grade = grade_grade::fetch(array('id'=>$id))) {
return null;
}
//extra security check - the grade item must be in this tree
if (!$item_el = $this->locate_element('i'.$grade->itemid)) {
return null;
}
$grade->grade_item =& $item_el['object']; // this may speedup grade_grade methods!
return array('eid'=>'g'.$id,'object'=>$grade, 'type'=>'grade');
}
// it is a category or item
foreach ($this->levels as $row) {
foreach ($row as $element) {
if ($element['type'] == 'filler') {
continue;
}
if ($element['eid'] == $eid) {
return $element;
}
}
}
return null;
}
}

View File

@ -1,50 +0,0 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999-2004 Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Unit tests for grade_tree object.
*
* @author nicolas@moodle.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package moodlecore
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->libdir.'/simpletest/fixtures/gradetest.php');
class grade_tree_test extends grade_test {
function test_grade_tree_locate_element() {
//TODO: add test
}
function test_grade_tree_constructor() {
$tree = new grade_tree($this->courseid);
}
}

View File

@ -91,7 +91,6 @@ require_once($CFG->libdir . '/grade/grade_grade.php');
require_once($CFG->libdir . '/grade/grade_scale.php');
require_once($CFG->libdir . '/grade/grade_outcome.php');
require_once($CFG->libdir . '/grade/grade_grade_text.php');
require_once($CFG->libdir . '/grade/grade_tree.php');
/***** PUBLIC GRADE API *****/