|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00026 require_once $CFG->libdir.'/gradelib.php'; 00027 00035 class graded_users_iterator { 00036 public $course; 00037 public $grade_items; 00038 public $groupid; 00039 public $users_rs; 00040 public $grades_rs; 00041 public $gradestack; 00042 public $sortfield1; 00043 public $sortorder1; 00044 public $sortfield2; 00045 public $sortorder2; 00046 00058 public function graded_users_iterator($course, $grade_items=null, $groupid=0, 00059 $sortfield1='lastname', $sortorder1='ASC', 00060 $sortfield2='firstname', $sortorder2='ASC') { 00061 $this->course = $course; 00062 $this->grade_items = $grade_items; 00063 $this->groupid = $groupid; 00064 $this->sortfield1 = $sortfield1; 00065 $this->sortorder1 = $sortorder1; 00066 $this->sortfield2 = $sortfield2; 00067 $this->sortorder2 = $sortorder2; 00068 00069 $this->gradestack = array(); 00070 } 00071 00076 public function init() { 00077 global $CFG, $DB; 00078 00079 $this->close(); 00080 00081 grade_regrade_final_grades($this->course->id); 00082 $course_item = grade_item::fetch_course_item($this->course->id); 00083 if ($course_item->needsupdate) { 00084 // can not calculate all final grades - sorry 00085 return false; 00086 } 00087 00088 $coursecontext = get_context_instance(CONTEXT_COURSE, $this->course->id); 00089 $relatedcontexts = get_related_contexts_string($coursecontext); 00090 00091 list($gradebookroles_sql, $params) = 00092 $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr'); 00093 00094 //limit to users with an active enrolment 00095 list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext); 00096 00097 $params = array_merge($params, $enrolledparams); 00098 00099 if ($this->groupid) { 00100 $groupsql = "INNER JOIN {groups_members} gm ON gm.userid = u.id"; 00101 $groupwheresql = "AND gm.groupid = :groupid"; 00102 // $params contents: gradebookroles 00103 $params['groupid'] = $this->groupid; 00104 } else { 00105 $groupsql = ""; 00106 $groupwheresql = ""; 00107 } 00108 00109 if (empty($this->sortfield1)) { 00110 // we must do some sorting even if not specified 00111 $ofields = ", u.id AS usrt"; 00112 $order = "usrt ASC"; 00113 00114 } else { 00115 $ofields = ", u.$this->sortfield1 AS usrt1"; 00116 $order = "usrt1 $this->sortorder1"; 00117 if (!empty($this->sortfield2)) { 00118 $ofields .= ", u.$this->sortfield2 AS usrt2"; 00119 $order .= ", usrt2 $this->sortorder2"; 00120 } 00121 if ($this->sortfield1 != 'id' and $this->sortfield2 != 'id') { 00122 // user order MUST be the same in both queries, 00123 // must include the only unique user->id if not already present 00124 $ofields .= ", u.id AS usrt"; 00125 $order .= ", usrt ASC"; 00126 } 00127 } 00128 00129 // $params contents: gradebookroles and groupid (for $groupwheresql) 00130 $users_sql = "SELECT u.* $ofields 00131 FROM {user} u 00132 JOIN ($enrolledsql) je ON je.id = u.id 00133 $groupsql 00134 JOIN ( 00135 SELECT DISTINCT ra.userid 00136 FROM {role_assignments} ra 00137 WHERE ra.roleid $gradebookroles_sql 00138 AND ra.contextid $relatedcontexts 00139 ) rainner ON rainner.userid = u.id 00140 WHERE u.deleted = 0 00141 $groupwheresql 00142 ORDER BY $order"; 00143 $this->users_rs = $DB->get_recordset_sql($users_sql, $params); 00144 00145 if (!empty($this->grade_items)) { 00146 $itemids = array_keys($this->grade_items); 00147 list($itemidsql, $grades_params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED, 'items'); 00148 $params = array_merge($params, $grades_params); 00149 // $params contents: gradebookroles, enrolledparams, groupid (for $groupwheresql) and itemids 00150 00151 $grades_sql = "SELECT g.* $ofields 00152 FROM {grade_grades} g 00153 JOIN {user} u ON g.userid = u.id 00154 JOIN ($enrolledsql) je ON je.id = u.id 00155 $groupsql 00156 JOIN ( 00157 SELECT DISTINCT ra.userid 00158 FROM {role_assignments} ra 00159 WHERE ra.roleid $gradebookroles_sql 00160 AND ra.contextid $relatedcontexts 00161 ) rainner ON rainner.userid = u.id 00162 WHERE u.deleted = 0 00163 AND g.itemid $itemidsql 00164 $groupwheresql 00165 ORDER BY $order, g.itemid ASC"; 00166 $this->grades_rs = $DB->get_recordset_sql($grades_sql, $params); 00167 } else { 00168 $this->grades_rs = false; 00169 } 00170 00171 return true; 00172 } 00173 00178 function next_user() { 00179 if (!$this->users_rs) { 00180 return false; // no users present 00181 } 00182 00183 if (!$this->users_rs->valid()) { 00184 if ($current = $this->_pop()) { 00185 // this is not good - user or grades updated between the two reads above :-( 00186 } 00187 00188 return false; // no more users 00189 } else { 00190 $user = $this->users_rs->current(); 00191 $this->users_rs->next(); 00192 } 00193 00194 // find grades of this user 00195 $grade_records = array(); 00196 while (true) { 00197 if (!$current = $this->_pop()) { 00198 break; // no more grades 00199 } 00200 00201 if (empty($current->userid)) { 00202 break; 00203 } 00204 00205 if ($current->userid != $user->id) { 00206 // grade of the next user, we have all for this user 00207 $this->_push($current); 00208 break; 00209 } 00210 00211 $grade_records[$current->itemid] = $current; 00212 } 00213 00214 $grades = array(); 00215 $feedbacks = array(); 00216 00217 if (!empty($this->grade_items)) { 00218 foreach ($this->grade_items as $grade_item) { 00219 if (array_key_exists($grade_item->id, $grade_records)) { 00220 $feedbacks[$grade_item->id]->feedback = $grade_records[$grade_item->id]->feedback; 00221 $feedbacks[$grade_item->id]->feedbackformat = $grade_records[$grade_item->id]->feedbackformat; 00222 unset($grade_records[$grade_item->id]->feedback); 00223 unset($grade_records[$grade_item->id]->feedbackformat); 00224 $grades[$grade_item->id] = new grade_grade($grade_records[$grade_item->id], false); 00225 } else { 00226 $feedbacks[$grade_item->id]->feedback = ''; 00227 $feedbacks[$grade_item->id]->feedbackformat = FORMAT_MOODLE; 00228 $grades[$grade_item->id] = 00229 new grade_grade(array('userid'=>$user->id, 'itemid'=>$grade_item->id), false); 00230 } 00231 } 00232 } 00233 00234 $result = new stdClass(); 00235 $result->user = $user; 00236 $result->grades = $grades; 00237 $result->feedbacks = $feedbacks; 00238 return $result; 00239 } 00240 00245 function close() { 00246 if ($this->users_rs) { 00247 $this->users_rs->close(); 00248 $this->users_rs = null; 00249 } 00250 if ($this->grades_rs) { 00251 $this->grades_rs->close(); 00252 $this->grades_rs = null; 00253 } 00254 $this->gradestack = array(); 00255 } 00256 00257 00265 function _push($grade) { 00266 array_push($this->gradestack, $grade); 00267 } 00268 00269 00275 function _pop() { 00276 global $DB; 00277 if (empty($this->gradestack)) { 00278 if (empty($this->grades_rs) || !$this->grades_rs->valid()) { 00279 return null; // no grades present 00280 } 00281 00282 $current = $this->grades_rs->current(); 00283 00284 $this->grades_rs->next(); 00285 00286 return $current; 00287 } else { 00288 return array_pop($this->gradestack); 00289 } 00290 } 00291 } 00292 00306 function print_graded_users_selector($course, $actionpage, $userid=0, $groupid=0, $includeall=true, $return=false) { 00307 global $CFG, $USER, $OUTPUT; 00308 return $OUTPUT->render(grade_get_graded_users_select(substr($actionpage, 0, strpos($actionpage, '/')), $course, $userid, $groupid, $includeall)); 00309 } 00310 00311 function grade_get_graded_users_select($report, $course, $userid, $groupid, $includeall) { 00312 global $USER; 00313 00314 if (is_null($userid)) { 00315 $userid = $USER->id; 00316 } 00317 00318 $menu = array(); // Will be a list of userid => user name 00319 $gui = new graded_users_iterator($course, null, $groupid); 00320 $gui->init(); 00321 $label = get_string('selectauser', 'grades'); 00322 if ($includeall) { 00323 $menu[0] = get_string('allusers', 'grades'); 00324 $label = get_string('selectalloroneuser', 'grades'); 00325 } 00326 while ($userdata = $gui->next_user()) { 00327 $user = $userdata->user; 00328 $menu[$user->id] = fullname($user); 00329 } 00330 $gui->close(); 00331 00332 if ($includeall) { 00333 $menu[0] .= " (" . (count($menu) - 1) . ")"; 00334 } 00335 $select = new single_select(new moodle_url('/grade/report/'.$report.'/index.php', array('id'=>$course->id)), 'userid', $menu, $userid); 00336 $select->label = $label; 00337 $select->formid = 'choosegradeuser'; 00338 return $select; 00339 } 00340 00349 function print_grade_plugin_selector($plugin_info, $active_type, $active_plugin, $return=false) { 00350 global $CFG, $OUTPUT, $PAGE; 00351 00352 $menu = array(); 00353 $count = 0; 00354 $active = ''; 00355 00356 foreach ($plugin_info as $plugin_type => $plugins) { 00357 if ($plugin_type == 'strings') { 00358 continue; 00359 } 00360 00361 $first_plugin = reset($plugins); 00362 00363 $sectionname = $plugin_info['strings'][$plugin_type]; 00364 $section = array(); 00365 00366 foreach ($plugins as $plugin) { 00367 $link = $plugin->link->out(false); 00368 $section[$link] = $plugin->string; 00369 $count++; 00370 if ($plugin_type === $active_type and $plugin->id === $active_plugin) { 00371 $active = $link; 00372 } 00373 } 00374 00375 if ($section) { 00376 $menu[] = array($sectionname=>$section); 00377 } 00378 } 00379 00380 // finally print/return the popup form 00381 if ($count > 1) { 00382 $select = new url_select($menu, $active, null, 'choosepluginreport'); 00383 00384 if ($return) { 00385 return $OUTPUT->render($select); 00386 } else { 00387 echo $OUTPUT->render($select); 00388 } 00389 } else { 00390 // only one option - no plugin selector needed 00391 return ''; 00392 } 00393 } 00394 00405 function grade_print_tabs($active_type, $active_plugin, $plugin_info, $return=false) { 00406 global $CFG, $COURSE; 00407 00408 if (!isset($currenttab)) { //TODO: this is weird 00409 $currenttab = ''; 00410 } 00411 00412 $tabs = array(); 00413 $top_row = array(); 00414 $bottom_row = array(); 00415 $inactive = array($active_plugin); 00416 $activated = array(); 00417 00418 $count = 0; 00419 $active = ''; 00420 00421 foreach ($plugin_info as $plugin_type => $plugins) { 00422 if ($plugin_type == 'strings') { 00423 continue; 00424 } 00425 00426 // If $plugins is actually the definition of a child-less parent link: 00427 if (!empty($plugins->id)) { 00428 $string = $plugins->string; 00429 if (!empty($plugin_info[$active_type]->parent)) { 00430 $string = $plugin_info[$active_type]->parent->string; 00431 } 00432 00433 $top_row[] = new tabobject($plugin_type, $plugins->link, $string); 00434 continue; 00435 } 00436 00437 $first_plugin = reset($plugins); 00438 $url = $first_plugin->link; 00439 00440 if ($plugin_type == 'report') { 00441 $url = $CFG->wwwroot.'/grade/report/index.php?id='.$COURSE->id; 00442 } 00443 00444 $top_row[] = new tabobject($plugin_type, $url, $plugin_info['strings'][$plugin_type]); 00445 00446 if ($active_type == $plugin_type) { 00447 foreach ($plugins as $plugin) { 00448 $bottom_row[] = new tabobject($plugin->id, $plugin->link, $plugin->string); 00449 if ($plugin->id == $active_plugin) { 00450 $inactive = array($plugin->id); 00451 } 00452 } 00453 } 00454 } 00455 00456 $tabs[] = $top_row; 00457 $tabs[] = $bottom_row; 00458 00459 if ($return) { 00460 return print_tabs($tabs, $active_type, $inactive, $activated, true); 00461 } else { 00462 print_tabs($tabs, $active_type, $inactive, $activated); 00463 } 00464 } 00465 00475 function grade_get_plugin_info($courseid, $active_type, $active_plugin) { 00476 global $CFG, $SITE; 00477 00478 $context = get_context_instance(CONTEXT_COURSE, $courseid); 00479 00480 $plugin_info = array(); 00481 $count = 0; 00482 $active = ''; 00483 $url_prefix = $CFG->wwwroot . '/grade/'; 00484 00485 // Language strings 00486 $plugin_info['strings'] = grade_helper::get_plugin_strings(); 00487 00488 if ($reports = grade_helper::get_plugins_reports($courseid)) { 00489 $plugin_info['report'] = $reports; 00490 } 00491 00492 //showing grade categories and items make no sense if we're not within a course 00493 if ($courseid!=$SITE->id) { 00494 if ($edittree = grade_helper::get_info_edit_structure($courseid)) { 00495 $plugin_info['edittree'] = $edittree; 00496 } 00497 } 00498 00499 if ($scale = grade_helper::get_info_scales($courseid)) { 00500 $plugin_info['scale'] = array('view'=>$scale); 00501 } 00502 00503 if ($outcomes = grade_helper::get_info_outcomes($courseid)) { 00504 $plugin_info['outcome'] = $outcomes; 00505 } 00506 00507 if ($letters = grade_helper::get_info_letters($courseid)) { 00508 $plugin_info['letter'] = $letters; 00509 } 00510 00511 if ($imports = grade_helper::get_plugins_import($courseid)) { 00512 $plugin_info['import'] = $imports; 00513 } 00514 00515 if ($exports = grade_helper::get_plugins_export($courseid)) { 00516 $plugin_info['export'] = $exports; 00517 } 00518 00519 foreach ($plugin_info as $plugin_type => $plugins) { 00520 if (!empty($plugins->id) && $active_plugin == $plugins->id) { 00521 $plugin_info['strings']['active_plugin_str'] = $plugins->string; 00522 break; 00523 } 00524 foreach ($plugins as $plugin) { 00525 if (is_a($plugin, 'grade_plugin_info')) { 00526 if ($active_plugin == $plugin->id) { 00527 $plugin_info['strings']['active_plugin_str'] = $plugin->string; 00528 } 00529 } 00530 } 00531 } 00532 00533 //hide course settings if we're not in a course 00534 if ($courseid!=$SITE->id) { 00535 if ($setting = grade_helper::get_info_manage_settings($courseid)) { 00536 $plugin_info['settings'] = array('course'=>$setting); 00537 } 00538 } 00539 00540 // Put preferences last 00541 if ($preferences = grade_helper::get_plugins_report_preferences($courseid)) { 00542 $plugin_info['preferences'] = $preferences; 00543 } 00544 00545 foreach ($plugin_info as $plugin_type => $plugins) { 00546 if (!empty($plugins->id) && $active_plugin == $plugins->id) { 00547 $plugin_info['strings']['active_plugin_str'] = $plugins->string; 00548 break; 00549 } 00550 foreach ($plugins as $plugin) { 00551 if (is_a($plugin, 'grade_plugin_info')) { 00552 if ($active_plugin == $plugin->id) { 00553 $plugin_info['strings']['active_plugin_str'] = $plugin->string; 00554 } 00555 } 00556 } 00557 } 00558 00559 return $plugin_info; 00560 } 00561 00570 class grade_plugin_info { 00576 public $id; 00582 public $link; 00588 public $string; 00594 public $parent; 00595 00606 public function __construct($id, $link, $string, $parent=null) { 00607 $this->id = $id; 00608 $this->link = $link; 00609 $this->string = $string; 00610 $this->parent = $parent; 00611 } 00612 } 00613 00633 function print_grade_page_head($courseid, $active_type, $active_plugin=null, 00634 $heading = false, $return=false, 00635 $buttons=false, $shownavigation=true) { 00636 global $CFG, $OUTPUT, $PAGE; 00637 00638 $plugin_info = grade_get_plugin_info($courseid, $active_type, $active_plugin); 00639 00640 // Determine the string of the active plugin 00641 $stractive_plugin = ($active_plugin) ? $plugin_info['strings']['active_plugin_str'] : $heading; 00642 $stractive_type = $plugin_info['strings'][$active_type]; 00643 00644 if (empty($plugin_info[$active_type]->id) || !empty($plugin_info[$active_type]->parent)) { 00645 $title = $PAGE->course->fullname.': ' . $stractive_type . ': ' . $stractive_plugin; 00646 } else { 00647 $title = $PAGE->course->fullname.': ' . $stractive_plugin; 00648 } 00649 00650 if ($active_type == 'report') { 00651 $PAGE->set_pagelayout('report'); 00652 } else { 00653 $PAGE->set_pagelayout('admin'); 00654 } 00655 $PAGE->set_title(get_string('grades') . ': ' . $stractive_type); 00656 $PAGE->set_heading($title); 00657 if ($buttons instanceof single_button) { 00658 $buttons = $OUTPUT->render($buttons); 00659 } 00660 $PAGE->set_button($buttons); 00661 grade_extend_settings($plugin_info, $courseid); 00662 00663 $returnval = $OUTPUT->header(); 00664 if (!$return) { 00665 echo $returnval; 00666 } 00667 00668 // Guess heading if not given explicitly 00669 if (!$heading) { 00670 $heading = $stractive_plugin; 00671 } 00672 00673 if ($shownavigation) { 00674 if ($CFG->grade_navmethod == GRADE_NAVMETHOD_COMBO || $CFG->grade_navmethod == GRADE_NAVMETHOD_DROPDOWN) { 00675 $returnval .= print_grade_plugin_selector($plugin_info, $active_type, $active_plugin, $return); 00676 } 00677 00678 if ($return) { 00679 $returnval .= $OUTPUT->heading($heading); 00680 } else { 00681 echo $OUTPUT->heading($heading); 00682 } 00683 00684 if ($CFG->grade_navmethod == GRADE_NAVMETHOD_COMBO || $CFG->grade_navmethod == GRADE_NAVMETHOD_TABS) { 00685 $returnval .= grade_print_tabs($active_type, $active_plugin, $plugin_info, $return); 00686 } 00687 } 00688 00689 if ($return) { 00690 return $returnval; 00691 } 00692 } 00693 00701 class grade_plugin_return { 00702 public $type; 00703 public $plugin; 00704 public $courseid; 00705 public $userid; 00706 public $page; 00707 00713 public function grade_plugin_return($params = null) { 00714 if (empty($params)) { 00715 $this->type = optional_param('gpr_type', null, PARAM_SAFEDIR); 00716 $this->plugin = optional_param('gpr_plugin', null, PARAM_PLUGIN); 00717 $this->courseid = optional_param('gpr_courseid', null, PARAM_INT); 00718 $this->userid = optional_param('gpr_userid', null, PARAM_INT); 00719 $this->page = optional_param('gpr_page', null, PARAM_INT); 00720 00721 } else { 00722 foreach ($params as $key=>$value) { 00723 if (property_exists($this, $key)) { 00724 $this->$key = $value; 00725 } 00726 } 00727 } 00728 } 00729 00734 public function get_options() { 00735 if (empty($this->type)) { 00736 return array(); 00737 } 00738 00739 $params = array(); 00740 00741 if (!empty($this->plugin)) { 00742 $params['plugin'] = $this->plugin; 00743 } 00744 00745 if (!empty($this->courseid)) { 00746 $params['id'] = $this->courseid; 00747 } 00748 00749 if (!empty($this->userid)) { 00750 $params['userid'] = $this->userid; 00751 } 00752 00753 if (!empty($this->page)) { 00754 $params['page'] = $this->page; 00755 } 00756 00757 return $params; 00758 } 00759 00768 public function get_return_url($default, $extras=null) { 00769 global $CFG; 00770 00771 if (empty($this->type) or empty($this->plugin)) { 00772 return $default; 00773 } 00774 00775 $url = $CFG->wwwroot.'/grade/'.$this->type.'/'.$this->plugin.'/index.php'; 00776 $glue = '?'; 00777 00778 if (!empty($this->courseid)) { 00779 $url .= $glue.'id='.$this->courseid; 00780 $glue = '&'; 00781 } 00782 00783 if (!empty($this->userid)) { 00784 $url .= $glue.'userid='.$this->userid; 00785 $glue = '&'; 00786 } 00787 00788 if (!empty($this->page)) { 00789 $url .= $glue.'page='.$this->page; 00790 $glue = '&'; 00791 } 00792 00793 if (!empty($extras)) { 00794 foreach ($extras as $key=>$value) { 00795 $url .= $glue.$key.'='.$value; 00796 $glue = '&'; 00797 } 00798 } 00799 00800 return $url; 00801 } 00802 00807 public function get_form_fields() { 00808 if (empty($this->type)) { 00809 return ''; 00810 } 00811 00812 $result = '<input type="hidden" name="gpr_type" value="'.$this->type.'" />'; 00813 00814 if (!empty($this->plugin)) { 00815 $result .= '<input type="hidden" name="gpr_plugin" value="'.$this->plugin.'" />'; 00816 } 00817 00818 if (!empty($this->courseid)) { 00819 $result .= '<input type="hidden" name="gpr_courseid" value="'.$this->courseid.'" />'; 00820 } 00821 00822 if (!empty($this->userid)) { 00823 $result .= '<input type="hidden" name="gpr_userid" value="'.$this->userid.'" />'; 00824 } 00825 00826 if (!empty($this->page)) { 00827 $result .= '<input type="hidden" name="gpr_page" value="'.$this->page.'" />'; 00828 } 00829 } 00830 00838 public function add_mform_elements(&$mform) { 00839 if (empty($this->type)) { 00840 return; 00841 } 00842 00843 $mform->addElement('hidden', 'gpr_type', $this->type); 00844 $mform->setType('gpr_type', PARAM_SAFEDIR); 00845 00846 if (!empty($this->plugin)) { 00847 $mform->addElement('hidden', 'gpr_plugin', $this->plugin); 00848 $mform->setType('gpr_plugin', PARAM_PLUGIN); 00849 } 00850 00851 if (!empty($this->courseid)) { 00852 $mform->addElement('hidden', 'gpr_courseid', $this->courseid); 00853 $mform->setType('gpr_courseid', PARAM_INT); 00854 } 00855 00856 if (!empty($this->userid)) { 00857 $mform->addElement('hidden', 'gpr_userid', $this->userid); 00858 $mform->setType('gpr_userid', PARAM_INT); 00859 } 00860 00861 if (!empty($this->page)) { 00862 $mform->addElement('hidden', 'gpr_page', $this->page); 00863 $mform->setType('gpr_page', PARAM_INT); 00864 } 00865 } 00866 00874 public function add_url_params(moodle_url $url) { 00875 if (empty($this->type)) { 00876 return $url; 00877 } 00878 00879 $url->param('gpr_type', $this->type); 00880 00881 if (!empty($this->plugin)) { 00882 $url->param('gpr_plugin', $this->plugin); 00883 } 00884 00885 if (!empty($this->courseid)) { 00886 $url->param('gpr_courseid' ,$this->courseid); 00887 } 00888 00889 if (!empty($this->userid)) { 00890 $url->param('gpr_userid', $this->userid); 00891 } 00892 00893 if (!empty($this->page)) { 00894 $url->param('gpr_page', $this->page); 00895 } 00896 00897 return $url; 00898 } 00899 } 00900 00911 function grade_build_nav($path, $pagename=null, $id=null) { 00912 global $CFG, $COURSE, $PAGE; 00913 00914 $strgrades = get_string('grades', 'grades'); 00915 00916 // Parse the path and build navlinks from its elements 00917 $dirroot_length = strlen($CFG->dirroot) + 1; // Add 1 for the first slash 00918 $path = substr($path, $dirroot_length); 00919 $path = str_replace('\\', '/', $path); 00920 00921 $path_elements = explode('/', $path); 00922 00923 $path_elements_count = count($path_elements); 00924 00925 // First link is always 'grade' 00926 $PAGE->navbar->add($strgrades, new moodle_url('/grade/index.php', array('id'=>$COURSE->id))); 00927 00928 $link = null; 00929 $numberofelements = 3; 00930 00931 // Prepare URL params string 00932 $linkparams = array(); 00933 if (!is_null($id)) { 00934 if (is_array($id)) { 00935 foreach ($id as $idkey => $idvalue) { 00936 $linkparams[$idkey] = $idvalue; 00937 } 00938 } else { 00939 $linkparams['id'] = $id; 00940 } 00941 } 00942 00943 $navlink4 = null; 00944 00945 // Remove file extensions from filenames 00946 foreach ($path_elements as $key => $filename) { 00947 $path_elements[$key] = str_replace('.php', '', $filename); 00948 } 00949 00950 // Second level links 00951 switch ($path_elements[1]) { 00952 case 'edit': // No link 00953 if ($path_elements[3] != 'index.php') { 00954 $numberofelements = 4; 00955 } 00956 break; 00957 case 'import': // No link 00958 break; 00959 case 'export': // No link 00960 break; 00961 case 'report': 00962 // $id is required for this link. Do not print it if $id isn't given 00963 if (!is_null($id)) { 00964 $link = new moodle_url('/grade/report/index.php', $linkparams); 00965 } 00966 00967 if ($path_elements[2] == 'grader') { 00968 $numberofelements = 4; 00969 } 00970 break; 00971 00972 default: 00973 // If this element isn't among the ones already listed above, it isn't supported, throw an error. 00974 debugging("grade_build_nav() doesn't support ". $path_elements[1] . 00975 " as the second path element after 'grade'."); 00976 return false; 00977 } 00978 $PAGE->navbar->add(get_string($path_elements[1], 'grades'), $link); 00979 00980 // Third level links 00981 if (empty($pagename)) { 00982 $pagename = get_string($path_elements[2], 'grades'); 00983 } 00984 00985 switch ($numberofelements) { 00986 case 3: 00987 $PAGE->navbar->add($pagename, $link); 00988 break; 00989 case 4: 00990 if ($path_elements[2] == 'grader' AND $path_elements[3] != 'index.php') { 00991 $PAGE->navbar->add(get_string('pluginname', 'gradereport_grader'), new moodle_url('/grade/report/grader/index.php', $linkparams)); 00992 } 00993 $PAGE->navbar->add($pagename); 00994 break; 00995 } 00996 00997 return ''; 00998 } 00999 01007 class grade_structure { 01008 public $context; 01009 01010 public $courseid; 01011 01018 public $modinfo; 01019 01023 public $items; 01024 01033 public function get_element_icon(&$element, $spacerifnone=false) { 01034 global $CFG, $OUTPUT; 01035 01036 switch ($element['type']) { 01037 case 'item': 01038 case 'courseitem': 01039 case 'categoryitem': 01040 $is_course = $element['object']->is_course_item(); 01041 $is_category = $element['object']->is_category_item(); 01042 $is_scale = $element['object']->gradetype == GRADE_TYPE_SCALE; 01043 $is_value = $element['object']->gradetype == GRADE_TYPE_VALUE; 01044 $is_outcome = !empty($element['object']->outcomeid); 01045 01046 if ($element['object']->is_calculated()) { 01047 $strcalc = get_string('calculatedgrade', 'grades'); 01048 return '<img src="'.$OUTPUT->pix_url('i/calc') . '" class="icon itemicon" title="'. 01049 s($strcalc).'" alt="'.s($strcalc).'"/>'; 01050 01051 } else if (($is_course or $is_category) and ($is_scale or $is_value)) { 01052 if ($category = $element['object']->get_item_category()) { 01053 switch ($category->aggregation) { 01054 case GRADE_AGGREGATE_MEAN: 01055 case GRADE_AGGREGATE_MEDIAN: 01056 case GRADE_AGGREGATE_WEIGHTED_MEAN: 01057 case GRADE_AGGREGATE_WEIGHTED_MEAN2: 01058 case GRADE_AGGREGATE_EXTRACREDIT_MEAN: 01059 $stragg = get_string('aggregation', 'grades'); 01060 return '<img src="'.$OUTPUT->pix_url('i/agg_mean') . '" ' . 01061 'class="icon itemicon" title="'.s($stragg).'" alt="'.s($stragg).'"/>'; 01062 case GRADE_AGGREGATE_SUM: 01063 $stragg = get_string('aggregation', 'grades'); 01064 return '<img src="'.$OUTPUT->pix_url('i/agg_sum') . '" ' . 01065 'class="icon itemicon" title="'.s($stragg).'" alt="'.s($stragg).'"/>'; 01066 } 01067 } 01068 01069 } else if ($element['object']->itemtype == 'mod') { 01070 //prevent outcomes being displaying the same icon as the activity they are attached to 01071 if ($is_outcome) { 01072 $stroutcome = s(get_string('outcome', 'grades')); 01073 return '<img src="'.$OUTPUT->pix_url('i/outcomes') . '" ' . 01074 'class="icon itemicon" title="'.$stroutcome. 01075 '" alt="'.$stroutcome.'"/>'; 01076 } else { 01077 $strmodname = get_string('modulename', $element['object']->itemmodule); 01078 return '<img src="'.$OUTPUT->pix_url('icon', 01079 $element['object']->itemmodule) . '" ' . 01080 'class="icon itemicon" title="' .s($strmodname). 01081 '" alt="' .s($strmodname).'"/>'; 01082 } 01083 } else if ($element['object']->itemtype == 'manual') { 01084 if ($element['object']->is_outcome_item()) { 01085 $stroutcome = get_string('outcome', 'grades'); 01086 return '<img src="'.$OUTPUT->pix_url('i/outcomes') . '" ' . 01087 'class="icon itemicon" title="'.s($stroutcome). 01088 '" alt="'.s($stroutcome).'"/>'; 01089 } else { 01090 $strmanual = get_string('manualitem', 'grades'); 01091 return '<img src="'.$OUTPUT->pix_url('t/manual_item') . '" '. 01092 'class="icon itemicon" title="'.s($strmanual). 01093 '" alt="'.s($strmanual).'"/>'; 01094 } 01095 } 01096 break; 01097 01098 case 'category': 01099 $strcat = get_string('category', 'grades'); 01100 return '<img src="'.$OUTPUT->pix_url('f/folder') . '" class="icon itemicon" ' . 01101 'title="'.s($strcat).'" alt="'.s($strcat).'" />'; 01102 } 01103 01104 if ($spacerifnone) { 01105 return $OUTPUT->spacer().' '; 01106 } else { 01107 return ''; 01108 } 01109 } 01110 01121 public function get_element_header(&$element, $withlink=false, $icon=true, $spacerifnone=false) { 01122 $header = ''; 01123 01124 if ($icon) { 01125 $header .= $this->get_element_icon($element, $spacerifnone); 01126 } 01127 01128 $header .= $element['object']->get_name(); 01129 01130 if ($element['type'] != 'item' and $element['type'] != 'categoryitem' and 01131 $element['type'] != 'courseitem') { 01132 return $header; 01133 } 01134 01135 if ($withlink) { 01136 $url = $this->get_activity_link($element); 01137 if ($url) { 01138 $a = new stdClass(); 01139 $a->name = get_string('modulename', $element['object']->itemmodule); 01140 $title = get_string('linktoactivity', 'grades', $a); 01141 01142 $header = html_writer::link($url, $header, array('title' => $title)); 01143 } 01144 } 01145 01146 return $header; 01147 } 01148 01149 private function get_activity_link($element) { 01150 global $CFG; 01152 static $hasgradephp = array(); 01153 01154 $itemtype = $element['object']->itemtype; 01155 $itemmodule = $element['object']->itemmodule; 01156 $iteminstance = $element['object']->iteminstance; 01157 $itemnumber = $element['object']->itemnumber; 01158 01159 // Links only for module items that have valid instance, module and are 01160 // called from grade_tree with valid modinfo 01161 if ($itemtype != 'mod' || !$iteminstance || !$itemmodule || !$this->modinfo) { 01162 return null; 01163 } 01164 01165 // Get $cm efficiently and with visibility information using modinfo 01166 $instances = $this->modinfo->get_instances(); 01167 if (empty($instances[$itemmodule][$iteminstance])) { 01168 return null; 01169 } 01170 $cm = $instances[$itemmodule][$iteminstance]; 01171 01172 // Do not add link if activity is not visible to the current user 01173 if (!$cm->uservisible) { 01174 return null; 01175 } 01176 01177 if (!array_key_exists($itemmodule, $hasgradephp)) { 01178 if (file_exists($CFG->dirroot . '/mod/' . $itemmodule . '/grade.php')) { 01179 $hasgradephp[$itemmodule] = true; 01180 } else { 01181 $hasgradephp[$itemmodule] = false; 01182 } 01183 } 01184 01185 // If module has grade.php, link to that, otherwise view.php 01186 if ($hasgradephp[$itemmodule]) { 01187 $args = array('id' => $cm->id, 'itemnumber' => $itemnumber); 01188 if (isset($element['userid'])) { 01189 $args['userid'] = $element['userid']; 01190 } 01191 return new moodle_url('/mod/' . $itemmodule . '/grade.php', $args); 01192 } else { 01193 return new moodle_url('/mod/' . $itemmodule . '/view.php', array('id' => $cm->id)); 01194 } 01195 } 01196 01206 public function get_grade_analysis_url(grade_grade $grade) { 01207 global $CFG; 01209 static $hasgradephp = array(); 01210 01211 if (empty($grade->grade_item) or !($grade->grade_item instanceof grade_item)) { 01212 throw new coding_exception('Passed grade without the associated grade item'); 01213 } 01214 $item = $grade->grade_item; 01215 01216 if (!$item->is_external_item()) { 01217 // at the moment, only activity modules are supported 01218 return null; 01219 } 01220 if ($item->itemtype !== 'mod') { 01221 throw new coding_exception('Unknown external itemtype: '.$item->itemtype); 01222 } 01223 if (empty($item->iteminstance) or empty($item->itemmodule) or empty($this->modinfo)) { 01224 return null; 01225 } 01226 01227 if (!array_key_exists($item->itemmodule, $hasgradephp)) { 01228 if (file_exists($CFG->dirroot . '/mod/' . $item->itemmodule . '/grade.php')) { 01229 $hasgradephp[$item->itemmodule] = true; 01230 } else { 01231 $hasgradephp[$item->itemmodule] = false; 01232 } 01233 } 01234 01235 if (!$hasgradephp[$item->itemmodule]) { 01236 return null; 01237 } 01238 01239 $instances = $this->modinfo->get_instances(); 01240 if (empty($instances[$item->itemmodule][$item->iteminstance])) { 01241 return null; 01242 } 01243 $cm = $instances[$item->itemmodule][$item->iteminstance]; 01244 if (!$cm->uservisible) { 01245 return null; 01246 } 01247 01248 $url = new moodle_url('/mod/'.$item->itemmodule.'/grade.php', array( 01249 'id' => $cm->id, 01250 'itemid' => $item->id, 01251 'itemnumber' => $item->itemnumber, 01252 'gradeid' => $grade->id, 01253 'userid' => $grade->userid, 01254 )); 01255 01256 return $url; 01257 } 01258 01265 public function get_grade_analysis_icon(grade_grade $grade) { 01266 global $OUTPUT; 01267 01268 $url = $this->get_grade_analysis_url($grade); 01269 if (is_null($url)) { 01270 return ''; 01271 } 01272 01273 return $OUTPUT->action_icon($url, new pix_icon('t/preview', 01274 get_string('gradeanalysis', 'core_grades'))); 01275 } 01276 01284 public function get_grade_eid($grade_grade) { 01285 if (empty($grade_grade->id)) { 01286 return 'n'.$grade_grade->itemid.'u'.$grade_grade->userid; 01287 } else { 01288 return 'g'.$grade_grade->id; 01289 } 01290 } 01291 01297 public function get_item_eid($grade_item) { 01298 return 'i'.$grade_item->id; 01299 } 01300 01309 public function get_params_for_iconstr($element) { 01310 $strparams = new stdClass(); 01311 $strparams->category = ''; 01312 $strparams->itemname = ''; 01313 $strparams->itemmodule = ''; 01314 01315 if (!method_exists($element['object'], 'get_name')) { 01316 return $strparams; 01317 } 01318 01319 $strparams->itemname = html_to_text($element['object']->get_name()); 01320 01321 // If element name is categorytotal, get the name of the parent category 01322 if ($strparams->itemname == get_string('categorytotal', 'grades')) { 01323 $parent = $element['object']->get_parent_category(); 01324 $strparams->category = $parent->get_name() . ' '; 01325 } else { 01326 $strparams->category = ''; 01327 } 01328 01329 $strparams->itemmodule = null; 01330 if (isset($element['object']->itemmodule)) { 01331 $strparams->itemmodule = $element['object']->itemmodule; 01332 } 01333 return $strparams; 01334 } 01335 01344 public function get_edit_icon($element, $gpr) { 01345 global $CFG, $OUTPUT; 01346 01347 if (!has_capability('moodle/grade:manage', $this->context)) { 01348 if ($element['type'] == 'grade' and has_capability('moodle/grade:edit', $this->context)) { 01349 // oki - let them override grade 01350 } else { 01351 return ''; 01352 } 01353 } 01354 01355 static $strfeedback = null; 01356 static $streditgrade = null; 01357 if (is_null($streditgrade)) { 01358 $streditgrade = get_string('editgrade', 'grades'); 01359 $strfeedback = get_string('feedback'); 01360 } 01361 01362 $strparams = $this->get_params_for_iconstr($element); 01363 01364 $object = $element['object']; 01365 01366 switch ($element['type']) { 01367 case 'item': 01368 case 'categoryitem': 01369 case 'courseitem': 01370 $stredit = get_string('editverbose', 'grades', $strparams); 01371 if (empty($object->outcomeid) || empty($CFG->enableoutcomes)) { 01372 $url = new moodle_url('/grade/edit/tree/item.php', 01373 array('courseid' => $this->courseid, 'id' => $object->id)); 01374 } else { 01375 $url = new moodle_url('/grade/edit/tree/outcomeitem.php', 01376 array('courseid' => $this->courseid, 'id' => $object->id)); 01377 } 01378 break; 01379 01380 case 'category': 01381 $stredit = get_string('editverbose', 'grades', $strparams); 01382 $url = new moodle_url('/grade/edit/tree/category.php', 01383 array('courseid' => $this->courseid, 'id' => $object->id)); 01384 break; 01385 01386 case 'grade': 01387 $stredit = $streditgrade; 01388 if (empty($object->id)) { 01389 $url = new moodle_url('/grade/edit/tree/grade.php', 01390 array('courseid' => $this->courseid, 'itemid' => $object->itemid, 'userid' => $object->userid)); 01391 } else { 01392 $url = new moodle_url('/grade/edit/tree/grade.php', 01393 array('courseid' => $this->courseid, 'id' => $object->id)); 01394 } 01395 if (!empty($object->feedback)) { 01396 $feedback = addslashes_js(trim(format_string($object->feedback, $object->feedbackformat))); 01397 } 01398 break; 01399 01400 default: 01401 $url = null; 01402 } 01403 01404 if ($url) { 01405 return $OUTPUT->action_icon($gpr->add_url_params($url), new pix_icon('t/edit', $stredit)); 01406 01407 } else { 01408 return ''; 01409 } 01410 } 01411 01420 public function get_hiding_icon($element, $gpr) { 01421 global $CFG, $OUTPUT; 01422 01423 if (!has_capability('moodle/grade:manage', $this->context) and 01424 !has_capability('moodle/grade:hide', $this->context)) { 01425 return ''; 01426 } 01427 01428 $strparams = $this->get_params_for_iconstr($element); 01429 $strshow = get_string('showverbose', 'grades', $strparams); 01430 $strhide = get_string('hideverbose', 'grades', $strparams); 01431 01432 $url = new moodle_url('/grade/edit/tree/action.php', array('id' => $this->courseid, 'sesskey' => sesskey(), 'eid' => $element['eid'])); 01433 $url = $gpr->add_url_params($url); 01434 01435 if ($element['object']->is_hidden()) { 01436 $type = 'show'; 01437 $tooltip = $strshow; 01438 01439 // Change the icon and add a tooltip showing the date 01440 if ($element['type'] != 'category' and $element['object']->get_hidden() > 1) { 01441 $type = 'hiddenuntil'; 01442 $tooltip = get_string('hiddenuntildate', 'grades', 01443 userdate($element['object']->get_hidden())); 01444 } 01445 01446 $url->param('action', 'show'); 01447 01448 $hideicon = $OUTPUT->action_icon($url, new pix_icon('t/'.$type, $tooltip, 'moodle', array('alt'=>$strshow, 'class'=>'iconsmall'))); 01449 01450 } else { 01451 $url->param('action', 'hide'); 01452 $hideicon = $OUTPUT->action_icon($url, new pix_icon('t/hide', $strhide)); 01453 } 01454 01455 return $hideicon; 01456 } 01457 01466 public function get_locking_icon($element, $gpr) { 01467 global $CFG, $OUTPUT; 01468 01469 $strparams = $this->get_params_for_iconstr($element); 01470 $strunlock = get_string('unlockverbose', 'grades', $strparams); 01471 $strlock = get_string('lockverbose', 'grades', $strparams); 01472 01473 $url = new moodle_url('/grade/edit/tree/action.php', array('id' => $this->courseid, 'sesskey' => sesskey(), 'eid' => $element['eid'])); 01474 $url = $gpr->add_url_params($url); 01475 01476 // Don't allow an unlocking action for a grade whose grade item is locked: just print a state icon 01477 if ($element['type'] == 'grade' && $element['object']->grade_item->is_locked()) { 01478 $strparamobj = new stdClass(); 01479 $strparamobj->itemname = $element['object']->grade_item->itemname; 01480 $strnonunlockable = get_string('nonunlockableverbose', 'grades', $strparamobj); 01481 01482 $action = $OUTPUT->pix_icon('t/unlock_gray', $strnonunlockable); 01483 01484 } else if ($element['object']->is_locked()) { 01485 $type = 'unlock'; 01486 $tooltip = $strunlock; 01487 01488 // Change the icon and add a tooltip showing the date 01489 if ($element['type'] != 'category' and $element['object']->get_locktime() > 1) { 01490 $type = 'locktime'; 01491 $tooltip = get_string('locktimedate', 'grades', 01492 userdate($element['object']->get_locktime())); 01493 } 01494 01495 if (!has_capability('moodle/grade:manage', $this->context) and !has_capability('moodle/grade:unlock', $this->context)) { 01496 $action = ''; 01497 } else { 01498 $url->param('action', 'unlock'); 01499 $action = $OUTPUT->action_icon($url, new pix_icon('t/'.$type, $tooltip, 'moodle', array('alt'=>$strunlock, 'class'=>'smallicon'))); 01500 } 01501 01502 } else { 01503 if (!has_capability('moodle/grade:manage', $this->context) and !has_capability('moodle/grade:lock', $this->context)) { 01504 $action = ''; 01505 } else { 01506 $url->param('action', 'lock'); 01507 $action = $OUTPUT->action_icon($url, new pix_icon('t/lock', $strlock)); 01508 } 01509 } 01510 01511 return $action; 01512 } 01513 01522 public function get_calculation_icon($element, $gpr) { 01523 global $CFG, $OUTPUT; 01524 if (!has_capability('moodle/grade:manage', $this->context)) { 01525 return ''; 01526 } 01527 01528 $type = $element['type']; 01529 $object = $element['object']; 01530 01531 if ($type == 'item' or $type == 'courseitem' or $type == 'categoryitem') { 01532 $strparams = $this->get_params_for_iconstr($element); 01533 $streditcalculation = get_string('editcalculationverbose', 'grades', $strparams); 01534 01535 $is_scale = $object->gradetype == GRADE_TYPE_SCALE; 01536 $is_value = $object->gradetype == GRADE_TYPE_VALUE; 01537 01538 // show calculation icon only when calculation possible 01539 if (!$object->is_external_item() and ($is_scale or $is_value)) { 01540 if ($object->is_calculated()) { 01541 $icon = 't/calc'; 01542 } else { 01543 $icon = 't/calc_off'; 01544 } 01545 01546 $url = new moodle_url('/grade/edit/tree/calculation.php', array('courseid' => $this->courseid, 'id' => $object->id)); 01547 $url = $gpr->add_url_params($url); 01548 return $OUTPUT->action_icon($url, new pix_icon($icon, $streditcalculation)) . "\n"; 01549 } 01550 } 01551 01552 return ''; 01553 } 01554 } 01555 01564 class grade_seq extends grade_structure { 01565 01569 public $elements; 01570 01579 public function grade_seq($courseid, $category_grade_last=false, $nooutcomes=false) { 01580 global $USER, $CFG; 01581 01582 $this->courseid = $courseid; 01583 $this->context = get_context_instance(CONTEXT_COURSE, $courseid); 01584 01585 // get course grade tree 01586 $top_element = grade_category::fetch_course_tree($courseid, true); 01587 01588 $this->elements = grade_seq::flatten($top_element, $category_grade_last, $nooutcomes); 01589 01590 foreach ($this->elements as $key=>$unused) { 01591 $this->items[$this->elements[$key]['object']->id] =& $this->elements[$key]['object']; 01592 } 01593 } 01594 01604 public function flatten(&$element, $category_grade_last, $nooutcomes) { 01605 if (empty($element['children'])) { 01606 return array(); 01607 } 01608 $children = array(); 01609 01610 foreach ($element['children'] as $sortorder=>$unused) { 01611 if ($nooutcomes and $element['type'] != 'category' and 01612 $element['children'][$sortorder]['object']->is_outcome_item()) { 01613 continue; 01614 } 01615 $children[] = $element['children'][$sortorder]; 01616 } 01617 unset($element['children']); 01618 01619 if ($category_grade_last and count($children) > 1) { 01620 $cat_item = array_shift($children); 01621 array_push($children, $cat_item); 01622 } 01623 01624 $result = array(); 01625 foreach ($children as $child) { 01626 if ($child['type'] == 'category') { 01627 $result = $result + grade_seq::flatten($child, $category_grade_last, $nooutcomes); 01628 } else { 01629 $child['eid'] = 'i'.$child['object']->id; 01630 $result[$child['object']->id] = $child; 01631 } 01632 } 01633 01634 return $result; 01635 } 01636 01645 public function locate_element($eid) { 01646 // it is a grade - construct a new object 01647 if (strpos($eid, 'n') === 0) { 01648 if (!preg_match('/n(\d+)u(\d+)/', $eid, $matches)) { 01649 return null; 01650 } 01651 01652 $itemid = $matches[1]; 01653 $userid = $matches[2]; 01654 01655 //extra security check - the grade item must be in this tree 01656 if (!$item_el = $this->locate_element('i'.$itemid)) { 01657 return null; 01658 } 01659 01660 // $gradea->id may be null - means does not exist yet 01661 $grade = new grade_grade(array('itemid'=>$itemid, 'userid'=>$userid)); 01662 01663 $grade->grade_item =& $item_el['object']; // this may speedup grade_grade methods! 01664 return array('eid'=>'n'.$itemid.'u'.$userid,'object'=>$grade, 'type'=>'grade'); 01665 01666 } else if (strpos($eid, 'g') === 0) { 01667 $id = (int) substr($eid, 1); 01668 if (!$grade = grade_grade::fetch(array('id'=>$id))) { 01669 return null; 01670 } 01671 //extra security check - the grade item must be in this tree 01672 if (!$item_el = $this->locate_element('i'.$grade->itemid)) { 01673 return null; 01674 } 01675 $grade->grade_item =& $item_el['object']; // this may speedup grade_grade methods! 01676 return array('eid'=>'g'.$id,'object'=>$grade, 'type'=>'grade'); 01677 } 01678 01679 // it is a category or item 01680 foreach ($this->elements as $element) { 01681 if ($element['eid'] == $eid) { 01682 return $element; 01683 } 01684 } 01685 01686 return null; 01687 } 01688 } 01689 01701 class grade_tree extends grade_structure { 01702 01707 public $top_element; 01708 01713 public $levels; 01714 01719 public $items; 01720 01731 public function grade_tree($courseid, $fillers=true, $category_grade_last=false, 01732 $collapsed=null, $nooutcomes=false) { 01733 global $USER, $CFG, $COURSE, $DB; 01734 01735 $this->courseid = $courseid; 01736 $this->levels = array(); 01737 $this->context = get_context_instance(CONTEXT_COURSE, $courseid); 01738 01739 if (!empty($COURSE->id) && $COURSE->id == $this->courseid) { 01740 $course = $COURSE; 01741 } else { 01742 $course = $DB->get_record('course', array('id' => $this->courseid)); 01743 } 01744 $this->modinfo = get_fast_modinfo($course); 01745 01746 // get course grade tree 01747 $this->top_element = grade_category::fetch_course_tree($courseid, true); 01748 01749 // collapse the categories if requested 01750 if (!empty($collapsed)) { 01751 grade_tree::category_collapse($this->top_element, $collapsed); 01752 } 01753 01754 // no otucomes if requested 01755 if (!empty($nooutcomes)) { 01756 grade_tree::no_outcomes($this->top_element); 01757 } 01758 01759 // move category item to last position in category 01760 if ($category_grade_last) { 01761 grade_tree::category_grade_last($this->top_element); 01762 } 01763 01764 if ($fillers) { 01765 // inject fake categories == fillers 01766 grade_tree::inject_fillers($this->top_element, 0); 01767 // add colspans to categories and fillers 01768 grade_tree::inject_colspans($this->top_element); 01769 } 01770 01771 grade_tree::fill_levels($this->levels, $this->top_element, 0); 01772 01773 } 01774 01783 public function category_collapse(&$element, $collapsed) { 01784 if ($element['type'] != 'category') { 01785 return; 01786 } 01787 if (empty($element['children']) or count($element['children']) < 2) { 01788 return; 01789 } 01790 01791 if (in_array($element['object']->id, $collapsed['aggregatesonly'])) { 01792 $category_item = reset($element['children']); //keep only category item 01793 $element['children'] = array(key($element['children'])=>$category_item); 01794 01795 } else { 01796 if (in_array($element['object']->id, $collapsed['gradesonly'])) { // Remove category item 01797 reset($element['children']); 01798 $first_key = key($element['children']); 01799 unset($element['children'][$first_key]); 01800 } 01801 foreach ($element['children'] as $sortorder=>$child) { // Recurse through the element's children 01802 grade_tree::category_collapse($element['children'][$sortorder], $collapsed); 01803 } 01804 } 01805 } 01806 01814 public function no_outcomes(&$element) { 01815 if ($element['type'] != 'category') { 01816 return; 01817 } 01818 foreach ($element['children'] as $sortorder=>$child) { 01819 if ($element['children'][$sortorder]['type'] == 'item' 01820 and $element['children'][$sortorder]['object']->is_outcome_item()) { 01821 unset($element['children'][$sortorder]); 01822 01823 } else if ($element['children'][$sortorder]['type'] == 'category') { 01824 grade_tree::no_outcomes($element['children'][$sortorder]); 01825 } 01826 } 01827 } 01828 01836 public function category_grade_last(&$element) { 01837 if (empty($element['children'])) { 01838 return; 01839 } 01840 if (count($element['children']) < 2) { 01841 return; 01842 } 01843 $first_item = reset($element['children']); 01844 if ($first_item['type'] == 'categoryitem' or $first_item['type'] == 'courseitem') { 01845 // the category item might have been already removed 01846 $order = key($element['children']); 01847 unset($element['children'][$order]); 01848 $element['children'][$order] =& $first_item; 01849 } 01850 foreach ($element['children'] as $sortorder => $child) { 01851 grade_tree::category_grade_last($element['children'][$sortorder]); 01852 } 01853 } 01854 01863 public function fill_levels(&$levels, &$element, $depth) { 01864 if (!array_key_exists($depth, $levels)) { 01865 $levels[$depth] = array(); 01866 } 01867 01868 // prepare unique identifier 01869 if ($element['type'] == 'category') { 01870 $element['eid'] = 'c'.$element['object']->id; 01871 } else if (in_array($element['type'], array('item', 'courseitem', 'categoryitem'))) { 01872 $element['eid'] = 'i'.$element['object']->id; 01873 $this->items[$element['object']->id] =& $element['object']; 01874 } 01875 01876 $levels[$depth][] =& $element; 01877 $depth++; 01878 if (empty($element['children'])) { 01879 return; 01880 } 01881 $prev = 0; 01882 foreach ($element['children'] as $sortorder=>$child) { 01883 grade_tree::fill_levels($levels, $element['children'][$sortorder], $depth); 01884 $element['children'][$sortorder]['prev'] = $prev; 01885 $element['children'][$sortorder]['next'] = 0; 01886 if ($prev) { 01887 $element['children'][$prev]['next'] = $sortorder; 01888 } 01889 $prev = $sortorder; 01890 } 01891 } 01892 01901 public function inject_fillers(&$element, $depth) { 01902 $depth++; 01903 01904 if (empty($element['children'])) { 01905 return $depth; 01906 } 01907 $chdepths = array(); 01908 $chids = array_keys($element['children']); 01909 $last_child = end($chids); 01910 $first_child = reset($chids); 01911 01912 foreach ($chids as $chid) { 01913 $chdepths[$chid] = grade_tree::inject_fillers($element['children'][$chid], $depth); 01914 } 01915 arsort($chdepths); 01916 01917 $maxdepth = reset($chdepths); 01918 foreach ($chdepths as $chid=>$chd) { 01919 if ($chd == $maxdepth) { 01920 continue; 01921 } 01922 for ($i=0; $i < $maxdepth-$chd; $i++) { 01923 if ($chid == $first_child) { 01924 $type = 'fillerfirst'; 01925 } else if ($chid == $last_child) { 01926 $type = 'fillerlast'; 01927 } else { 01928 $type = 'filler'; 01929 } 01930 $oldchild =& $element['children'][$chid]; 01931 $element['children'][$chid] = array('object'=>'filler', 'type'=>$type, 01932 'eid'=>'', 'depth'=>$element['object']->depth, 01933 'children'=>array($oldchild)); 01934 } 01935 } 01936 01937 return $maxdepth; 01938 } 01939 01947 public function inject_colspans(&$element) { 01948 if (empty($element['children'])) { 01949 return 1; 01950 } 01951 $count = 0; 01952 foreach ($element['children'] as $key=>$child) { 01953 $count += grade_tree::inject_colspans($element['children'][$key]); 01954 } 01955 $element['colspan'] = $count; 01956 return $count; 01957 } 01958 01965 public function locate_element($eid) { 01966 // it is a grade - construct a new object 01967 if (strpos($eid, 'n') === 0) { 01968 if (!preg_match('/n(\d+)u(\d+)/', $eid, $matches)) { 01969 return null; 01970 } 01971 01972 $itemid = $matches[1]; 01973 $userid = $matches[2]; 01974 01975 //extra security check - the grade item must be in this tree 01976 if (!$item_el = $this->locate_element('i'.$itemid)) { 01977 return null; 01978 } 01979 01980 // $gradea->id may be null - means does not exist yet 01981 $grade = new grade_grade(array('itemid'=>$itemid, 'userid'=>$userid)); 01982 01983 $grade->grade_item =& $item_el['object']; // this may speedup grade_grade methods! 01984 return array('eid'=>'n'.$itemid.'u'.$userid,'object'=>$grade, 'type'=>'grade'); 01985 01986 } else if (strpos($eid, 'g') === 0) { 01987 $id = (int) substr($eid, 1); 01988 if (!$grade = grade_grade::fetch(array('id'=>$id))) { 01989 return null; 01990 } 01991 //extra security check - the grade item must be in this tree 01992 if (!$item_el = $this->locate_element('i'.$grade->itemid)) { 01993 return null; 01994 } 01995 $grade->grade_item =& $item_el['object']; // this may speedup grade_grade methods! 01996 return array('eid'=>'g'.$id,'object'=>$grade, 'type'=>'grade'); 01997 } 01998 01999 // it is a category or item 02000 foreach ($this->levels as $row) { 02001 foreach ($row as $element) { 02002 if ($element['type'] == 'filler') { 02003 continue; 02004 } 02005 if ($element['eid'] == $eid) { 02006 return $element; 02007 } 02008 } 02009 } 02010 02011 return null; 02012 } 02013 02022 public function exporttoxml($root=null, $tabs="\t") { 02023 $xml = null; 02024 $first = false; 02025 if (is_null($root)) { 02026 $root = $this->top_element; 02027 $xml = '<?xml version="1.0" encoding="UTF-8" ?>' . "\n"; 02028 $xml .= "<gradetree>\n"; 02029 $first = true; 02030 } 02031 02032 $type = 'undefined'; 02033 if (strpos($root['object']->table, 'grade_categories') !== false) { 02034 $type = 'category'; 02035 } else if (strpos($root['object']->table, 'grade_items') !== false) { 02036 $type = 'item'; 02037 } else if (strpos($root['object']->table, 'grade_outcomes') !== false) { 02038 $type = 'outcome'; 02039 } 02040 02041 $xml .= "$tabs<element type=\"$type\">\n"; 02042 foreach ($root['object'] as $var => $value) { 02043 if (!is_object($value) && !is_array($value) && !empty($value)) { 02044 $xml .= "$tabs\t<$var>$value</$var>\n"; 02045 } 02046 } 02047 02048 if (!empty($root['children'])) { 02049 $xml .= "$tabs\t<children>\n"; 02050 foreach ($root['children'] as $sortorder => $child) { 02051 $xml .= $this->exportToXML($child, $tabs."\t\t"); 02052 } 02053 $xml .= "$tabs\t</children>\n"; 02054 } 02055 02056 $xml .= "$tabs</element>\n"; 02057 02058 if ($first) { 02059 $xml .= "</gradetree>"; 02060 } 02061 02062 return $xml; 02063 } 02064 02073 public function exporttojson($root=null, $tabs="\t") { 02074 $json = null; 02075 $first = false; 02076 if (is_null($root)) { 02077 $root = $this->top_element; 02078 $first = true; 02079 } 02080 02081 $name = ''; 02082 02083 02084 if (strpos($root['object']->table, 'grade_categories') !== false) { 02085 $name = $root['object']->fullname; 02086 if ($name == '?') { 02087 $name = $root['object']->get_name(); 02088 } 02089 } else if (strpos($root['object']->table, 'grade_items') !== false) { 02090 $name = $root['object']->itemname; 02091 } else if (strpos($root['object']->table, 'grade_outcomes') !== false) { 02092 $name = $root['object']->itemname; 02093 } 02094 02095 $json .= "$tabs {\n"; 02096 $json .= "$tabs\t \"type\": \"{$root['type']}\",\n"; 02097 $json .= "$tabs\t \"name\": \"$name\",\n"; 02098 02099 foreach ($root['object'] as $var => $value) { 02100 if (!is_object($value) && !is_array($value) && !empty($value)) { 02101 $json .= "$tabs\t \"$var\": \"$value\",\n"; 02102 } 02103 } 02104 02105 $json = substr($json, 0, strrpos($json, ',')); 02106 02107 if (!empty($root['children'])) { 02108 $json .= ",\n$tabs\t\"children\": [\n"; 02109 foreach ($root['children'] as $sortorder => $child) { 02110 $json .= $this->exportToJSON($child, $tabs."\t\t"); 02111 } 02112 $json = substr($json, 0, strrpos($json, ',')); 02113 $json .= "\n$tabs\t]\n"; 02114 } 02115 02116 if ($first) { 02117 $json .= "\n}"; 02118 } else { 02119 $json .= "\n$tabs},\n"; 02120 } 02121 02122 return $json; 02123 } 02124 02130 public function get_levels() { 02131 return $this->levels; 02132 } 02133 02139 public function get_items() { 02140 return $this->items; 02141 } 02142 02150 public function get_item($itemid) { 02151 if (array_key_exists($itemid, $this->items)) { 02152 return $this->items[$itemid]; 02153 } else { 02154 return false; 02155 } 02156 } 02157 } 02158 02166 function grade_button($type, $courseid, $object) { 02167 global $CFG, $OUTPUT; 02168 if (preg_match('/grade_(.*)/', get_class($object), $matches)) { 02169 $objectidstring = $matches[1] . 'id'; 02170 } else { 02171 throw new coding_exception('grade_button() only accepts grade_* objects as third parameter!'); 02172 } 02173 02174 $strdelete = get_string('delete'); 02175 $stredit = get_string('edit'); 02176 02177 if ($type == 'delete') { 02178 $url = new moodle_url('index.php', array('id' => $courseid, $objectidstring => $object->id, 'action' => 'delete', 'sesskey' => sesskey())); 02179 } else if ($type == 'edit') { 02180 $url = new moodle_url('edit.php', array('courseid' => $courseid, 'id' => $object->id)); 02181 } 02182 02183 return $OUTPUT->action_icon($url, new pix_icon('t/'.$type, ${'str'.$type})); 02184 02185 } 02186 02193 function grade_extend_settings($plugininfo, $courseid) { 02194 global $PAGE; 02195 02196 $gradenode = $PAGE->settingsnav->prepend(get_string('gradeadministration', 'grades'), null, navigation_node::TYPE_CONTAINER); 02197 02198 $strings = array_shift($plugininfo); 02199 02200 if ($reports = grade_helper::get_plugins_reports($courseid)) { 02201 foreach ($reports as $report) { 02202 $gradenode->add($report->string, $report->link, navigation_node::TYPE_SETTING, null, $report->id, new pix_icon('i/report', '')); 02203 } 02204 } 02205 02206 if ($imports = grade_helper::get_plugins_import($courseid)) { 02207 $importnode = $gradenode->add($strings['import'], null, navigation_node::TYPE_CONTAINER); 02208 foreach ($imports as $import) { 02209 $importnode->add($import->string, $import->link, navigation_node::TYPE_SETTING, null, $import->id, new pix_icon('i/restore', '')); 02210 } 02211 } 02212 02213 if ($exports = grade_helper::get_plugins_export($courseid)) { 02214 $exportnode = $gradenode->add($strings['export'], null, navigation_node::TYPE_CONTAINER); 02215 foreach ($exports as $export) { 02216 $exportnode->add($export->string, $export->link, navigation_node::TYPE_SETTING, null, $export->id, new pix_icon('i/backup', '')); 02217 } 02218 } 02219 02220 if ($setting = grade_helper::get_info_manage_settings($courseid)) { 02221 $gradenode->add(get_string('coursegradesettings', 'grades'), $setting->link, navigation_node::TYPE_SETTING, null, $setting->id, new pix_icon('i/settings', '')); 02222 } 02223 02224 if ($preferences = grade_helper::get_plugins_report_preferences($courseid)) { 02225 $preferencesnode = $gradenode->add(get_string('myreportpreferences', 'grades'), null, navigation_node::TYPE_CONTAINER); 02226 foreach ($preferences as $preference) { 02227 $preferencesnode->add($preference->string, $preference->link, navigation_node::TYPE_SETTING, null, $preference->id, new pix_icon('i/settings', '')); 02228 } 02229 } 02230 02231 if ($letters = grade_helper::get_info_letters($courseid)) { 02232 $letters = array_shift($letters); 02233 $gradenode->add($strings['letter'], $letters->link, navigation_node::TYPE_SETTING, null, $letters->id, new pix_icon('i/settings', '')); 02234 } 02235 02236 if ($outcomes = grade_helper::get_info_outcomes($courseid)) { 02237 $outcomes = array_shift($outcomes); 02238 $gradenode->add($strings['outcome'], $outcomes->link, navigation_node::TYPE_SETTING, null, $outcomes->id, new pix_icon('i/outcomes', '')); 02239 } 02240 02241 if ($scales = grade_helper::get_info_scales($courseid)) { 02242 $gradenode->add($strings['scale'], $scales->link, navigation_node::TYPE_SETTING, null, $scales->id, new pix_icon('i/scales', '')); 02243 } 02244 02245 if ($categories = grade_helper::get_info_edit_structure($courseid)) { 02246 $categoriesnode = $gradenode->add(get_string('categoriesanditems','grades'), null, navigation_node::TYPE_CONTAINER); 02247 foreach ($categories as $category) { 02248 $categoriesnode->add($category->string, $category->link, navigation_node::TYPE_SETTING, null, $category->id, new pix_icon('i/report', '')); 02249 } 02250 } 02251 02252 if ($gradenode->contains_active_node()) { 02253 // If the gradenode is active include the settings base node (gradeadministration) in 02254 // the navbar, typcially this is ignored. 02255 $PAGE->navbar->includesettingsbase = true; 02256 02257 // If we can get the course admin node make sure it is closed by default 02258 // as in this case the gradenode will be opened 02259 if ($coursenode = $PAGE->settingsnav->get('courseadmin', navigation_node::TYPE_COURSE)){ 02260 $coursenode->make_inactive(); 02261 $coursenode->forceopen = false; 02262 } 02263 } 02264 } 02265 02275 abstract class grade_helper { 02280 protected static $managesetting = null; 02285 protected static $gradereports = null; 02290 protected static $gradereportpreferences = null; 02295 protected static $scaleinfo = null; 02300 protected static $outcomeinfo = null; 02305 protected static $edittree = null; 02310 protected static $letterinfo = null; 02315 protected static $importplugins = null; 02320 protected static $exportplugins = null; 02325 protected static $pluginstrings = null; 02326 02342 public static function get_plugin_strings() { 02343 if (self::$pluginstrings === null) { 02344 self::$pluginstrings = array( 02345 'report' => get_string('view'), 02346 'edittree' => get_string('edittree', 'grades'), 02347 'scale' => get_string('scales'), 02348 'outcome' => get_string('outcomes', 'grades'), 02349 'letter' => get_string('letters', 'grades'), 02350 'export' => get_string('export', 'grades'), 02351 'import' => get_string('import'), 02352 'preferences' => get_string('mypreferences', 'grades'), 02353 'settings' => get_string('settings') 02354 ); 02355 } 02356 return self::$pluginstrings; 02357 } 02364 public static function get_info_manage_settings($courseid) { 02365 if (self::$managesetting !== null) { 02366 return self::$managesetting; 02367 } 02368 $context = get_context_instance(CONTEXT_COURSE, $courseid); 02369 if (has_capability('moodle/course:update', $context)) { 02370 self::$managesetting = new grade_plugin_info('coursesettings', new moodle_url('/grade/edit/settings/index.php', array('id'=>$courseid)), get_string('course')); 02371 } else { 02372 self::$managesetting = false; 02373 } 02374 return self::$managesetting; 02375 } 02382 public static function get_plugins_reports($courseid) { 02383 global $SITE; 02384 02385 if (self::$gradereports !== null) { 02386 return self::$gradereports; 02387 } 02388 $context = get_context_instance(CONTEXT_COURSE, $courseid); 02389 $gradereports = array(); 02390 $gradepreferences = array(); 02391 foreach (get_plugin_list('gradereport') as $plugin => $plugindir) { 02392 //some reports make no sense if we're not within a course 02393 if ($courseid==$SITE->id && ($plugin=='grader' || $plugin=='user')) { 02394 continue; 02395 } 02396 02397 // Remove ones we can't see 02398 if (!has_capability('gradereport/'.$plugin.':view', $context)) { 02399 continue; 02400 } 02401 02402 $pluginstr = get_string('pluginname', 'gradereport_'.$plugin); 02403 $url = new moodle_url('/grade/report/'.$plugin.'/index.php', array('id'=>$courseid)); 02404 $gradereports[$plugin] = new grade_plugin_info($plugin, $url, $pluginstr); 02405 02406 // Add link to preferences tab if such a page exists 02407 if (file_exists($plugindir.'/preferences.php')) { 02408 $url = new moodle_url('/grade/report/'.$plugin.'/preferences.php', array('id'=>$courseid)); 02409 $gradepreferences[$plugin] = new grade_plugin_info($plugin, $url, $pluginstr); 02410 } 02411 } 02412 if (count($gradereports) == 0) { 02413 $gradereports = false; 02414 $gradepreferences = false; 02415 } else if (count($gradepreferences) == 0) { 02416 $gradepreferences = false; 02417 asort($gradereports); 02418 } else { 02419 asort($gradereports); 02420 asort($gradepreferences); 02421 } 02422 self::$gradereports = $gradereports; 02423 self::$gradereportpreferences = $gradepreferences; 02424 return self::$gradereports; 02425 } 02432 public static function get_plugins_report_preferences($courseid) { 02433 if (self::$gradereportpreferences !== null) { 02434 return self::$gradereportpreferences; 02435 } 02436 self::get_plugins_reports($courseid); 02437 return self::$gradereportpreferences; 02438 } 02444 public static function get_info_scales($courseid) { 02445 if (self::$scaleinfo !== null) { 02446 return self::$scaleinfo; 02447 } 02448 if (has_capability('moodle/course:managescales', get_context_instance(CONTEXT_COURSE, $courseid))) { 02449 $url = new moodle_url('/grade/edit/scale/index.php', array('id'=>$courseid)); 02450 self::$scaleinfo = new grade_plugin_info('scale', $url, get_string('view')); 02451 } else { 02452 self::$scaleinfo = false; 02453 } 02454 return self::$scaleinfo; 02455 } 02461 public static function get_info_outcomes($courseid) { 02462 global $CFG, $SITE; 02463 02464 if (self::$outcomeinfo !== null) { 02465 return self::$outcomeinfo; 02466 } 02467 $context = get_context_instance(CONTEXT_COURSE, $courseid); 02468 $canmanage = has_capability('moodle/grade:manage', $context); 02469 $canupdate = has_capability('moodle/course:update', $context); 02470 if (!empty($CFG->enableoutcomes) && ($canmanage || $canupdate)) { 02471 $outcomes = array(); 02472 if ($canupdate) { 02473 if ($courseid!=$SITE->id) { 02474 $url = new moodle_url('/grade/edit/outcome/course.php', array('id'=>$courseid)); 02475 $outcomes['course'] = new grade_plugin_info('course', $url, get_string('outcomescourse', 'grades')); 02476 } 02477 $url = new moodle_url('/grade/edit/outcome/index.php', array('id'=>$courseid)); 02478 $outcomes['edit'] = new grade_plugin_info('edit', $url, get_string('editoutcomes', 'grades')); 02479 $url = new moodle_url('/grade/edit/outcome/import.php', array('courseid'=>$courseid)); 02480 $outcomes['import'] = new grade_plugin_info('import', $url, get_string('importoutcomes', 'grades')); 02481 } else { 02482 if ($courseid!=$SITE->id) { 02483 $url = new moodle_url('/grade/edit/outcome/course.php', array('id'=>$courseid)); 02484 $outcomes['edit'] = new grade_plugin_info('edit', $url, get_string('outcomescourse', 'grades')); 02485 } 02486 } 02487 self::$outcomeinfo = $outcomes; 02488 } else { 02489 self::$outcomeinfo = false; 02490 } 02491 return self::$outcomeinfo; 02492 } 02498 public static function get_info_edit_structure($courseid) { 02499 if (self::$edittree !== null) { 02500 return self::$edittree; 02501 } 02502 if (has_capability('moodle/grade:manage', get_context_instance(CONTEXT_COURSE, $courseid))) { 02503 $url = new moodle_url('/grade/edit/tree/index.php', array('sesskey'=>sesskey(), 'showadvanced'=>'0', 'id'=>$courseid)); 02504 self::$edittree = array( 02505 'simpleview' => new grade_plugin_info('simpleview', $url, get_string('simpleview', 'grades')), 02506 'fullview' => new grade_plugin_info('fullview', new moodle_url($url, array('showadvanced'=>'1')), get_string('fullview', 'grades')) 02507 ); 02508 } else { 02509 self::$edittree = false; 02510 } 02511 return self::$edittree; 02512 } 02518 public static function get_info_letters($courseid) { 02519 if (self::$letterinfo !== null) { 02520 return self::$letterinfo; 02521 } 02522 $context = get_context_instance(CONTEXT_COURSE, $courseid); 02523 $canmanage = has_capability('moodle/grade:manage', $context); 02524 $canmanageletters = has_capability('moodle/grade:manageletters', $context); 02525 if ($canmanage || $canmanageletters) { 02526 self::$letterinfo = array( 02527 'view' => new grade_plugin_info('view', new moodle_url('/grade/edit/letter/index.php', array('id'=>$context->id)), get_string('view')), 02528 'edit' => new grade_plugin_info('edit', new moodle_url('/grade/edit/letter/index.php', array('edit'=>1,'id'=>$context->id)), get_string('edit')) 02529 ); 02530 } else { 02531 self::$letterinfo = false; 02532 } 02533 return self::$letterinfo; 02534 } 02540 public static function get_plugins_import($courseid) { 02541 global $CFG; 02542 02543 if (self::$importplugins !== null) { 02544 return self::$importplugins; 02545 } 02546 $importplugins = array(); 02547 $context = get_context_instance(CONTEXT_COURSE, $courseid); 02548 02549 if (has_capability('moodle/grade:import', $context)) { 02550 foreach (get_plugin_list('gradeimport') as $plugin => $plugindir) { 02551 if (!has_capability('gradeimport/'.$plugin.':view', $context)) { 02552 continue; 02553 } 02554 $pluginstr = get_string('pluginname', 'gradeimport_'.$plugin); 02555 $url = new moodle_url('/grade/import/'.$plugin.'/index.php', array('id'=>$courseid)); 02556 $importplugins[$plugin] = new grade_plugin_info($plugin, $url, $pluginstr); 02557 } 02558 02559 02560 if ($CFG->gradepublishing) { 02561 $url = new moodle_url('/grade/import/keymanager.php', array('id'=>$courseid)); 02562 $importplugins['keymanager'] = new grade_plugin_info('keymanager', $url, get_string('keymanager', 'grades')); 02563 } 02564 } 02565 02566 if (count($importplugins) > 0) { 02567 asort($importplugins); 02568 self::$importplugins = $importplugins; 02569 } else { 02570 self::$importplugins = false; 02571 } 02572 return self::$importplugins; 02573 } 02579 public static function get_plugins_export($courseid) { 02580 global $CFG; 02581 02582 if (self::$exportplugins !== null) { 02583 return self::$exportplugins; 02584 } 02585 $context = get_context_instance(CONTEXT_COURSE, $courseid); 02586 $exportplugins = array(); 02587 if (has_capability('moodle/grade:export', $context)) { 02588 foreach (get_plugin_list('gradeexport') as $plugin => $plugindir) { 02589 if (!has_capability('gradeexport/'.$plugin.':view', $context)) { 02590 continue; 02591 } 02592 $pluginstr = get_string('pluginname', 'gradeexport_'.$plugin); 02593 $url = new moodle_url('/grade/export/'.$plugin.'/index.php', array('id'=>$courseid)); 02594 $exportplugins[$plugin] = new grade_plugin_info($plugin, $url, $pluginstr); 02595 } 02596 02597 if ($CFG->gradepublishing) { 02598 $url = new moodle_url('/grade/export/keymanager.php', array('id'=>$courseid)); 02599 $exportplugins['keymanager'] = new grade_plugin_info('keymanager', $url, get_string('keymanager', 'grades')); 02600 } 02601 } 02602 if (count($exportplugins) > 0) { 02603 asort($exportplugins); 02604 self::$exportplugins = $exportplugins; 02605 } else { 02606 self::$exportplugins = false; 02607 } 02608 return self::$exportplugins; 02609 } 02610 }