PageRenderTime 75ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/grade/lib.php

https://bitbucket.org/synergylearning/campusconnect
PHP | 2840 lines | 1843 code | 325 blank | 672 comment | 389 complexity | 2fea5cda5172928f8fd6dee352a6d6aa MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, LGPL-2.1, Apache-2.0, BSD-3-Clause, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Functions used by gradebook plugins and reports.
  18. *
  19. * @package core_grades
  20. * @copyright 2009 Petr Skoda and Nicolas Connault
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. require_once($CFG->libdir . '/gradelib.php');
  24. require_once($CFG->dirroot . '/grade/export/lib.php');
  25. /**
  26. * This class iterates over all users that are graded in a course.
  27. * Returns detailed info about users and their grades.
  28. *
  29. * @author Petr Skoda <skodak@moodle.org>
  30. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31. */
  32. class graded_users_iterator {
  33. /**
  34. * The couse whose users we are interested in
  35. */
  36. protected $course;
  37. /**
  38. * An array of grade items or null if only user data was requested
  39. */
  40. protected $grade_items;
  41. /**
  42. * The group ID we are interested in. 0 means all groups.
  43. */
  44. protected $groupid;
  45. /**
  46. * A recordset of graded users
  47. */
  48. protected $users_rs;
  49. /**
  50. * A recordset of user grades (grade_grade instances)
  51. */
  52. protected $grades_rs;
  53. /**
  54. * Array used when moving to next user while iterating through the grades recordset
  55. */
  56. protected $gradestack;
  57. /**
  58. * The first field of the users table by which the array of users will be sorted
  59. */
  60. protected $sortfield1;
  61. /**
  62. * Should sortfield1 be ASC or DESC
  63. */
  64. protected $sortorder1;
  65. /**
  66. * The second field of the users table by which the array of users will be sorted
  67. */
  68. protected $sortfield2;
  69. /**
  70. * Should sortfield2 be ASC or DESC
  71. */
  72. protected $sortorder2;
  73. /**
  74. * Should users whose enrolment has been suspended be ignored?
  75. */
  76. protected $onlyactive = false;
  77. /**
  78. * Enable user custom fields
  79. */
  80. protected $allowusercustomfields = false;
  81. /**
  82. * List of suspended users in course. This includes users whose enrolment status is suspended
  83. * or enrolment has expired or not started.
  84. */
  85. protected $suspendedusers = array();
  86. /**
  87. * Constructor
  88. *
  89. * @param object $course A course object
  90. * @param array $grade_items array of grade items, if not specified only user info returned
  91. * @param int $groupid iterate only group users if present
  92. * @param string $sortfield1 The first field of the users table by which the array of users will be sorted
  93. * @param string $sortorder1 The order in which the first sorting field will be sorted (ASC or DESC)
  94. * @param string $sortfield2 The second field of the users table by which the array of users will be sorted
  95. * @param string $sortorder2 The order in which the second sorting field will be sorted (ASC or DESC)
  96. */
  97. public function __construct($course, $grade_items=null, $groupid=0,
  98. $sortfield1='lastname', $sortorder1='ASC',
  99. $sortfield2='firstname', $sortorder2='ASC') {
  100. $this->course = $course;
  101. $this->grade_items = $grade_items;
  102. $this->groupid = $groupid;
  103. $this->sortfield1 = $sortfield1;
  104. $this->sortorder1 = $sortorder1;
  105. $this->sortfield2 = $sortfield2;
  106. $this->sortorder2 = $sortorder2;
  107. $this->gradestack = array();
  108. }
  109. /**
  110. * Initialise the iterator
  111. *
  112. * @return boolean success
  113. */
  114. public function init() {
  115. global $CFG, $DB;
  116. $this->close();
  117. export_verify_grades($this->course->id);
  118. $course_item = grade_item::fetch_course_item($this->course->id);
  119. if ($course_item->needsupdate) {
  120. // Can not calculate all final grades - sorry.
  121. return false;
  122. }
  123. $coursecontext = context_course::instance($this->course->id);
  124. list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
  125. list($gradebookroles_sql, $params) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr');
  126. list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext, '', 0, $this->onlyactive);
  127. $params = array_merge($params, $enrolledparams, $relatedctxparams);
  128. if ($this->groupid) {
  129. $groupsql = "INNER JOIN {groups_members} gm ON gm.userid = u.id";
  130. $groupwheresql = "AND gm.groupid = :groupid";
  131. // $params contents: gradebookroles
  132. $params['groupid'] = $this->groupid;
  133. } else {
  134. $groupsql = "";
  135. $groupwheresql = "";
  136. }
  137. if (empty($this->sortfield1)) {
  138. // We must do some sorting even if not specified.
  139. $ofields = ", u.id AS usrt";
  140. $order = "usrt ASC";
  141. } else {
  142. $ofields = ", u.$this->sortfield1 AS usrt1";
  143. $order = "usrt1 $this->sortorder1";
  144. if (!empty($this->sortfield2)) {
  145. $ofields .= ", u.$this->sortfield2 AS usrt2";
  146. $order .= ", usrt2 $this->sortorder2";
  147. }
  148. if ($this->sortfield1 != 'id' and $this->sortfield2 != 'id') {
  149. // User order MUST be the same in both queries,
  150. // must include the only unique user->id if not already present.
  151. $ofields .= ", u.id AS usrt";
  152. $order .= ", usrt ASC";
  153. }
  154. }
  155. $userfields = 'u.*';
  156. $customfieldssql = '';
  157. if ($this->allowusercustomfields && !empty($CFG->grade_export_customprofilefields)) {
  158. $customfieldscount = 0;
  159. $customfieldsarray = grade_helper::get_user_profile_fields($this->course->id, $this->allowusercustomfields);
  160. foreach ($customfieldsarray as $field) {
  161. if (!empty($field->customid)) {
  162. $customfieldssql .= "
  163. LEFT JOIN (SELECT * FROM {user_info_data}
  164. WHERE fieldid = :cf$customfieldscount) cf$customfieldscount
  165. ON u.id = cf$customfieldscount.userid";
  166. $userfields .= ", cf$customfieldscount.data AS customfield_{$field->shortname}";
  167. $params['cf'.$customfieldscount] = $field->customid;
  168. $customfieldscount++;
  169. }
  170. }
  171. }
  172. $users_sql = "SELECT $userfields $ofields
  173. FROM {user} u
  174. JOIN ($enrolledsql) je ON je.id = u.id
  175. $groupsql $customfieldssql
  176. JOIN (
  177. SELECT DISTINCT ra.userid
  178. FROM {role_assignments} ra
  179. WHERE ra.roleid $gradebookroles_sql
  180. AND ra.contextid $relatedctxsql
  181. ) rainner ON rainner.userid = u.id
  182. WHERE u.deleted = 0
  183. $groupwheresql
  184. ORDER BY $order";
  185. $this->users_rs = $DB->get_recordset_sql($users_sql, $params);
  186. if (!$this->onlyactive) {
  187. $context = context_course::instance($this->course->id);
  188. $this->suspendedusers = get_suspended_userids($context);
  189. } else {
  190. $this->suspendedusers = array();
  191. }
  192. if (!empty($this->grade_items)) {
  193. $itemids = array_keys($this->grade_items);
  194. list($itemidsql, $grades_params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED, 'items');
  195. $params = array_merge($params, $grades_params);
  196. $grades_sql = "SELECT g.* $ofields
  197. FROM {grade_grades} g
  198. JOIN {user} u ON g.userid = u.id
  199. JOIN ($enrolledsql) je ON je.id = u.id
  200. $groupsql
  201. JOIN (
  202. SELECT DISTINCT ra.userid
  203. FROM {role_assignments} ra
  204. WHERE ra.roleid $gradebookroles_sql
  205. AND ra.contextid $relatedctxsql
  206. ) rainner ON rainner.userid = u.id
  207. WHERE u.deleted = 0
  208. AND g.itemid $itemidsql
  209. $groupwheresql
  210. ORDER BY $order, g.itemid ASC";
  211. $this->grades_rs = $DB->get_recordset_sql($grades_sql, $params);
  212. } else {
  213. $this->grades_rs = false;
  214. }
  215. return true;
  216. }
  217. /**
  218. * Returns information about the next user
  219. * @return mixed array of user info, all grades and feedback or null when no more users found
  220. */
  221. public function next_user() {
  222. if (!$this->users_rs) {
  223. return false; // no users present
  224. }
  225. if (!$this->users_rs->valid()) {
  226. if ($current = $this->_pop()) {
  227. // this is not good - user or grades updated between the two reads above :-(
  228. }
  229. return false; // no more users
  230. } else {
  231. $user = $this->users_rs->current();
  232. $this->users_rs->next();
  233. }
  234. // find grades of this user
  235. $grade_records = array();
  236. while (true) {
  237. if (!$current = $this->_pop()) {
  238. break; // no more grades
  239. }
  240. if (empty($current->userid)) {
  241. break;
  242. }
  243. if ($current->userid != $user->id) {
  244. // grade of the next user, we have all for this user
  245. $this->_push($current);
  246. break;
  247. }
  248. $grade_records[$current->itemid] = $current;
  249. }
  250. $grades = array();
  251. $feedbacks = array();
  252. if (!empty($this->grade_items)) {
  253. foreach ($this->grade_items as $grade_item) {
  254. if (!isset($feedbacks[$grade_item->id])) {
  255. $feedbacks[$grade_item->id] = new stdClass();
  256. }
  257. if (array_key_exists($grade_item->id, $grade_records)) {
  258. $feedbacks[$grade_item->id]->feedback = $grade_records[$grade_item->id]->feedback;
  259. $feedbacks[$grade_item->id]->feedbackformat = $grade_records[$grade_item->id]->feedbackformat;
  260. unset($grade_records[$grade_item->id]->feedback);
  261. unset($grade_records[$grade_item->id]->feedbackformat);
  262. $grades[$grade_item->id] = new grade_grade($grade_records[$grade_item->id], false);
  263. } else {
  264. $feedbacks[$grade_item->id]->feedback = '';
  265. $feedbacks[$grade_item->id]->feedbackformat = FORMAT_MOODLE;
  266. $grades[$grade_item->id] =
  267. new grade_grade(array('userid'=>$user->id, 'itemid'=>$grade_item->id), false);
  268. }
  269. }
  270. }
  271. // Set user suspended status.
  272. $user->suspendedenrolment = isset($this->suspendedusers[$user->id]);
  273. $result = new stdClass();
  274. $result->user = $user;
  275. $result->grades = $grades;
  276. $result->feedbacks = $feedbacks;
  277. return $result;
  278. }
  279. /**
  280. * Close the iterator, do not forget to call this function
  281. */
  282. public function close() {
  283. if ($this->users_rs) {
  284. $this->users_rs->close();
  285. $this->users_rs = null;
  286. }
  287. if ($this->grades_rs) {
  288. $this->grades_rs->close();
  289. $this->grades_rs = null;
  290. }
  291. $this->gradestack = array();
  292. }
  293. /**
  294. * Should all enrolled users be exported or just those with an active enrolment?
  295. *
  296. * @param bool $onlyactive True to limit the export to users with an active enrolment
  297. */
  298. public function require_active_enrolment($onlyactive = true) {
  299. if (!empty($this->users_rs)) {
  300. debugging('Calling require_active_enrolment() has no effect unless you call init() again', DEBUG_DEVELOPER);
  301. }
  302. $this->onlyactive = $onlyactive;
  303. }
  304. /**
  305. * Allow custom fields to be included
  306. *
  307. * @param bool $allow Whether to allow custom fields or not
  308. * @return void
  309. */
  310. public function allow_user_custom_fields($allow = true) {
  311. if ($allow) {
  312. $this->allowusercustomfields = true;
  313. } else {
  314. $this->allowusercustomfields = false;
  315. }
  316. }
  317. /**
  318. * Add a grade_grade instance to the grade stack
  319. *
  320. * @param grade_grade $grade Grade object
  321. *
  322. * @return void
  323. */
  324. private function _push($grade) {
  325. array_push($this->gradestack, $grade);
  326. }
  327. /**
  328. * Remove a grade_grade instance from the grade stack
  329. *
  330. * @return grade_grade current grade object
  331. */
  332. private function _pop() {
  333. global $DB;
  334. if (empty($this->gradestack)) {
  335. if (empty($this->grades_rs) || !$this->grades_rs->valid()) {
  336. return null; // no grades present
  337. }
  338. $current = $this->grades_rs->current();
  339. $this->grades_rs->next();
  340. return $current;
  341. } else {
  342. return array_pop($this->gradestack);
  343. }
  344. }
  345. }
  346. /**
  347. * Print a selection popup form of the graded users in a course.
  348. *
  349. * @deprecated since 2.0
  350. *
  351. * @param int $course id of the course
  352. * @param string $actionpage The page receiving the data from the popoup form
  353. * @param int $userid id of the currently selected user (or 'all' if they are all selected)
  354. * @param int $groupid id of requested group, 0 means all
  355. * @param int $includeall bool include all option
  356. * @param bool $return If true, will return the HTML, otherwise, will print directly
  357. * @return null
  358. */
  359. function print_graded_users_selector($course, $actionpage, $userid=0, $groupid=0, $includeall=true, $return=false) {
  360. global $CFG, $USER, $OUTPUT;
  361. return $OUTPUT->render(grade_get_graded_users_select(substr($actionpage, 0, strpos($actionpage, '/')), $course, $userid, $groupid, $includeall));
  362. }
  363. function grade_get_graded_users_select($report, $course, $userid, $groupid, $includeall) {
  364. global $USER, $CFG;
  365. if (is_null($userid)) {
  366. $userid = $USER->id;
  367. }
  368. $coursecontext = context_course::instance($course->id);
  369. $defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol);
  370. $showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol);
  371. $showonlyactiveenrol = $showonlyactiveenrol || !has_capability('moodle/course:viewsuspendedusers', $coursecontext);
  372. $menu = array(); // Will be a list of userid => user name
  373. $menususpendedusers = array(); // Suspended users go to a separate optgroup.
  374. $gui = new graded_users_iterator($course, null, $groupid);
  375. $gui->require_active_enrolment($showonlyactiveenrol);
  376. $gui->init();
  377. $label = get_string('selectauser', 'grades');
  378. if ($includeall) {
  379. $menu[0] = get_string('allusers', 'grades');
  380. $label = get_string('selectalloroneuser', 'grades');
  381. }
  382. while ($userdata = $gui->next_user()) {
  383. $user = $userdata->user;
  384. $userfullname = fullname($user);
  385. if ($user->suspendedenrolment) {
  386. $menususpendedusers[$user->id] = $userfullname;
  387. } else {
  388. $menu[$user->id] = $userfullname;
  389. }
  390. }
  391. $gui->close();
  392. if ($includeall) {
  393. $menu[0] .= " (" . (count($menu) + count($menususpendedusers) - 1) . ")";
  394. }
  395. if (!empty($menususpendedusers)) {
  396. $menu[] = array(get_string('suspendedusers') => $menususpendedusers);
  397. }
  398. $select = new single_select(new moodle_url('/grade/report/'.$report.'/index.php', array('id'=>$course->id)), 'userid', $menu, $userid);
  399. $select->label = $label;
  400. $select->formid = 'choosegradeuser';
  401. return $select;
  402. }
  403. /**
  404. * Print grading plugin selection popup form.
  405. *
  406. * @param array $plugin_info An array of plugins containing information for the selector
  407. * @param boolean $return return as string
  408. *
  409. * @return nothing or string if $return true
  410. */
  411. function print_grade_plugin_selector($plugin_info, $active_type, $active_plugin, $return=false) {
  412. global $CFG, $OUTPUT, $PAGE;
  413. $menu = array();
  414. $count = 0;
  415. $active = '';
  416. foreach ($plugin_info as $plugin_type => $plugins) {
  417. if ($plugin_type == 'strings') {
  418. continue;
  419. }
  420. $first_plugin = reset($plugins);
  421. $sectionname = $plugin_info['strings'][$plugin_type];
  422. $section = array();
  423. foreach ($plugins as $plugin) {
  424. $link = $plugin->link->out(false);
  425. $section[$link] = $plugin->string;
  426. $count++;
  427. if ($plugin_type === $active_type and $plugin->id === $active_plugin) {
  428. $active = $link;
  429. }
  430. }
  431. if ($section) {
  432. $menu[] = array($sectionname=>$section);
  433. }
  434. }
  435. // finally print/return the popup form
  436. if ($count > 1) {
  437. $select = new url_select($menu, $active, null, 'choosepluginreport');
  438. $select->set_label(get_string('gradereport', 'grades'), array('class' => 'accesshide'));
  439. if ($return) {
  440. return $OUTPUT->render($select);
  441. } else {
  442. echo $OUTPUT->render($select);
  443. }
  444. } else {
  445. // only one option - no plugin selector needed
  446. return '';
  447. }
  448. }
  449. /**
  450. * Print grading plugin selection tab-based navigation.
  451. *
  452. * @param string $active_type type of plugin on current page - import, export, report or edit
  453. * @param string $active_plugin active plugin type - grader, user, cvs, ...
  454. * @param array $plugin_info Array of plugins
  455. * @param boolean $return return as string
  456. *
  457. * @return nothing or string if $return true
  458. */
  459. function grade_print_tabs($active_type, $active_plugin, $plugin_info, $return=false) {
  460. global $CFG, $COURSE;
  461. if (!isset($currenttab)) { //TODO: this is weird
  462. $currenttab = '';
  463. }
  464. $tabs = array();
  465. $top_row = array();
  466. $bottom_row = array();
  467. $inactive = array($active_plugin);
  468. $activated = array();
  469. $count = 0;
  470. $active = '';
  471. foreach ($plugin_info as $plugin_type => $plugins) {
  472. if ($plugin_type == 'strings') {
  473. continue;
  474. }
  475. // If $plugins is actually the definition of a child-less parent link:
  476. if (!empty($plugins->id)) {
  477. $string = $plugins->string;
  478. if (!empty($plugin_info[$active_type]->parent)) {
  479. $string = $plugin_info[$active_type]->parent->string;
  480. }
  481. $top_row[] = new tabobject($plugin_type, $plugins->link, $string);
  482. continue;
  483. }
  484. $first_plugin = reset($plugins);
  485. $url = $first_plugin->link;
  486. if ($plugin_type == 'report') {
  487. $url = $CFG->wwwroot.'/grade/report/index.php?id='.$COURSE->id;
  488. }
  489. $top_row[] = new tabobject($plugin_type, $url, $plugin_info['strings'][$plugin_type]);
  490. if ($active_type == $plugin_type) {
  491. foreach ($plugins as $plugin) {
  492. $bottom_row[] = new tabobject($plugin->id, $plugin->link, $plugin->string);
  493. if ($plugin->id == $active_plugin) {
  494. $inactive = array($plugin->id);
  495. }
  496. }
  497. }
  498. }
  499. $tabs[] = $top_row;
  500. $tabs[] = $bottom_row;
  501. if ($return) {
  502. return print_tabs($tabs, $active_type, $inactive, $activated, true);
  503. } else {
  504. print_tabs($tabs, $active_type, $inactive, $activated);
  505. }
  506. }
  507. /**
  508. * grade_get_plugin_info
  509. *
  510. * @param int $courseid The course id
  511. * @param string $active_type type of plugin on current page - import, export, report or edit
  512. * @param string $active_plugin active plugin type - grader, user, cvs, ...
  513. *
  514. * @return array
  515. */
  516. function grade_get_plugin_info($courseid, $active_type, $active_plugin) {
  517. global $CFG, $SITE;
  518. $context = context_course::instance($courseid);
  519. $plugin_info = array();
  520. $count = 0;
  521. $active = '';
  522. $url_prefix = $CFG->wwwroot . '/grade/';
  523. // Language strings
  524. $plugin_info['strings'] = grade_helper::get_plugin_strings();
  525. if ($reports = grade_helper::get_plugins_reports($courseid)) {
  526. $plugin_info['report'] = $reports;
  527. }
  528. //showing grade categories and items make no sense if we're not within a course
  529. if ($courseid!=$SITE->id) {
  530. if ($edittree = grade_helper::get_info_edit_structure($courseid)) {
  531. $plugin_info['edittree'] = $edittree;
  532. }
  533. }
  534. if ($scale = grade_helper::get_info_scales($courseid)) {
  535. $plugin_info['scale'] = array('view'=>$scale);
  536. }
  537. if ($outcomes = grade_helper::get_info_outcomes($courseid)) {
  538. $plugin_info['outcome'] = $outcomes;
  539. }
  540. if ($letters = grade_helper::get_info_letters($courseid)) {
  541. $plugin_info['letter'] = $letters;
  542. }
  543. if ($imports = grade_helper::get_plugins_import($courseid)) {
  544. $plugin_info['import'] = $imports;
  545. }
  546. if ($exports = grade_helper::get_plugins_export($courseid)) {
  547. $plugin_info['export'] = $exports;
  548. }
  549. foreach ($plugin_info as $plugin_type => $plugins) {
  550. if (!empty($plugins->id) && $active_plugin == $plugins->id) {
  551. $plugin_info['strings']['active_plugin_str'] = $plugins->string;
  552. break;
  553. }
  554. foreach ($plugins as $plugin) {
  555. if (is_a($plugin, 'grade_plugin_info')) {
  556. if ($active_plugin == $plugin->id) {
  557. $plugin_info['strings']['active_plugin_str'] = $plugin->string;
  558. }
  559. }
  560. }
  561. }
  562. //hide course settings if we're not in a course
  563. if ($courseid!=$SITE->id) {
  564. if ($setting = grade_helper::get_info_manage_settings($courseid)) {
  565. $plugin_info['settings'] = array('course'=>$setting);
  566. }
  567. }
  568. // Put preferences last
  569. if ($preferences = grade_helper::get_plugins_report_preferences($courseid)) {
  570. $plugin_info['preferences'] = $preferences;
  571. }
  572. foreach ($plugin_info as $plugin_type => $plugins) {
  573. if (!empty($plugins->id) && $active_plugin == $plugins->id) {
  574. $plugin_info['strings']['active_plugin_str'] = $plugins->string;
  575. break;
  576. }
  577. foreach ($plugins as $plugin) {
  578. if (is_a($plugin, 'grade_plugin_info')) {
  579. if ($active_plugin == $plugin->id) {
  580. $plugin_info['strings']['active_plugin_str'] = $plugin->string;
  581. }
  582. }
  583. }
  584. }
  585. return $plugin_info;
  586. }
  587. /**
  588. * A simple class containing info about grade plugins.
  589. * Can be subclassed for special rules
  590. *
  591. * @package core_grades
  592. * @copyright 2009 Nicolas Connault
  593. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  594. */
  595. class grade_plugin_info {
  596. /**
  597. * A unique id for this plugin
  598. *
  599. * @var mixed
  600. */
  601. public $id;
  602. /**
  603. * A URL to access this plugin
  604. *
  605. * @var mixed
  606. */
  607. public $link;
  608. /**
  609. * The name of this plugin
  610. *
  611. * @var mixed
  612. */
  613. public $string;
  614. /**
  615. * Another grade_plugin_info object, parent of the current one
  616. *
  617. * @var mixed
  618. */
  619. public $parent;
  620. /**
  621. * Constructor
  622. *
  623. * @param int $id A unique id for this plugin
  624. * @param string $link A URL to access this plugin
  625. * @param string $string The name of this plugin
  626. * @param object $parent Another grade_plugin_info object, parent of the current one
  627. *
  628. * @return void
  629. */
  630. public function __construct($id, $link, $string, $parent=null) {
  631. $this->id = $id;
  632. $this->link = $link;
  633. $this->string = $string;
  634. $this->parent = $parent;
  635. }
  636. }
  637. /**
  638. * Prints the page headers, breadcrumb trail, page heading, (optional) dropdown navigation menu and
  639. * (optional) navigation tabs for any gradebook page. All gradebook pages MUST use these functions
  640. * in favour of the usual print_header(), print_header_simple(), print_heading() etc.
  641. * !IMPORTANT! Use of tabs.php file in gradebook pages is forbidden unless tabs are switched off at
  642. * the site level for the gradebook ($CFG->grade_navmethod = GRADE_NAVMETHOD_DROPDOWN).
  643. *
  644. * @param int $courseid Course id
  645. * @param string $active_type The type of the current page (report, settings,
  646. * import, export, scales, outcomes, letters)
  647. * @param string $active_plugin The plugin of the current page (grader, fullview etc...)
  648. * @param string $heading The heading of the page. Tries to guess if none is given
  649. * @param boolean $return Whether to return (true) or echo (false) the HTML generated by this function
  650. * @param string $bodytags Additional attributes that will be added to the <body> tag
  651. * @param string $buttons Additional buttons to display on the page
  652. * @param boolean $shownavigation should the gradebook navigation drop down (or tabs) be shown?
  653. *
  654. * @return string HTML code or nothing if $return == false
  655. */
  656. function print_grade_page_head($courseid, $active_type, $active_plugin=null,
  657. $heading = false, $return=false,
  658. $buttons=false, $shownavigation=true) {
  659. global $CFG, $OUTPUT, $PAGE;
  660. $plugin_info = grade_get_plugin_info($courseid, $active_type, $active_plugin);
  661. // Determine the string of the active plugin
  662. $stractive_plugin = ($active_plugin) ? $plugin_info['strings']['active_plugin_str'] : $heading;
  663. $stractive_type = $plugin_info['strings'][$active_type];
  664. if (empty($plugin_info[$active_type]->id) || !empty($plugin_info[$active_type]->parent)) {
  665. $title = $PAGE->course->fullname.': ' . $stractive_type . ': ' . $stractive_plugin;
  666. } else {
  667. $title = $PAGE->course->fullname.': ' . $stractive_plugin;
  668. }
  669. if ($active_type == 'report') {
  670. $PAGE->set_pagelayout('report');
  671. } else {
  672. $PAGE->set_pagelayout('admin');
  673. }
  674. $PAGE->set_title(get_string('grades') . ': ' . $stractive_type);
  675. $PAGE->set_heading($title);
  676. if ($buttons instanceof single_button) {
  677. $buttons = $OUTPUT->render($buttons);
  678. }
  679. $PAGE->set_button($buttons);
  680. grade_extend_settings($plugin_info, $courseid);
  681. $returnval = $OUTPUT->header();
  682. if (!$return) {
  683. echo $returnval;
  684. }
  685. // Guess heading if not given explicitly
  686. if (!$heading) {
  687. $heading = $stractive_plugin;
  688. }
  689. if ($shownavigation) {
  690. if ($CFG->grade_navmethod == GRADE_NAVMETHOD_COMBO || $CFG->grade_navmethod == GRADE_NAVMETHOD_DROPDOWN) {
  691. $returnval .= print_grade_plugin_selector($plugin_info, $active_type, $active_plugin, $return);
  692. }
  693. if ($return) {
  694. $returnval .= $OUTPUT->heading($heading);
  695. } else {
  696. echo $OUTPUT->heading($heading);
  697. }
  698. if ($CFG->grade_navmethod == GRADE_NAVMETHOD_COMBO || $CFG->grade_navmethod == GRADE_NAVMETHOD_TABS) {
  699. $returnval .= grade_print_tabs($active_type, $active_plugin, $plugin_info, $return);
  700. }
  701. }
  702. if ($return) {
  703. return $returnval;
  704. }
  705. }
  706. /**
  707. * Utility class used for return tracking when using edit and other forms in grade plugins
  708. *
  709. * @package core_grades
  710. * @copyright 2009 Nicolas Connault
  711. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  712. */
  713. class grade_plugin_return {
  714. public $type;
  715. public $plugin;
  716. public $courseid;
  717. public $userid;
  718. public $page;
  719. /**
  720. * Constructor
  721. *
  722. * @param array $params - associative array with return parameters, if null parameter are taken from _GET or _POST
  723. */
  724. public function grade_plugin_return($params = null) {
  725. if (empty($params)) {
  726. $this->type = optional_param('gpr_type', null, PARAM_SAFEDIR);
  727. $this->plugin = optional_param('gpr_plugin', null, PARAM_PLUGIN);
  728. $this->courseid = optional_param('gpr_courseid', null, PARAM_INT);
  729. $this->userid = optional_param('gpr_userid', null, PARAM_INT);
  730. $this->page = optional_param('gpr_page', null, PARAM_INT);
  731. } else {
  732. foreach ($params as $key=>$value) {
  733. if (property_exists($this, $key)) {
  734. $this->$key = $value;
  735. }
  736. }
  737. }
  738. }
  739. /**
  740. * Returns return parameters as options array suitable for buttons.
  741. * @return array options
  742. */
  743. public function get_options() {
  744. if (empty($this->type)) {
  745. return array();
  746. }
  747. $params = array();
  748. if (!empty($this->plugin)) {
  749. $params['plugin'] = $this->plugin;
  750. }
  751. if (!empty($this->courseid)) {
  752. $params['id'] = $this->courseid;
  753. }
  754. if (!empty($this->userid)) {
  755. $params['userid'] = $this->userid;
  756. }
  757. if (!empty($this->page)) {
  758. $params['page'] = $this->page;
  759. }
  760. return $params;
  761. }
  762. /**
  763. * Returns return url
  764. *
  765. * @param string $default default url when params not set
  766. * @param array $extras Extra URL parameters
  767. *
  768. * @return string url
  769. */
  770. public function get_return_url($default, $extras=null) {
  771. global $CFG;
  772. if (empty($this->type) or empty($this->plugin)) {
  773. return $default;
  774. }
  775. $url = $CFG->wwwroot.'/grade/'.$this->type.'/'.$this->plugin.'/index.php';
  776. $glue = '?';
  777. if (!empty($this->courseid)) {
  778. $url .= $glue.'id='.$this->courseid;
  779. $glue = '&amp;';
  780. }
  781. if (!empty($this->userid)) {
  782. $url .= $glue.'userid='.$this->userid;
  783. $glue = '&amp;';
  784. }
  785. if (!empty($this->page)) {
  786. $url .= $glue.'page='.$this->page;
  787. $glue = '&amp;';
  788. }
  789. if (!empty($extras)) {
  790. foreach ($extras as $key=>$value) {
  791. $url .= $glue.$key.'='.$value;
  792. $glue = '&amp;';
  793. }
  794. }
  795. return $url;
  796. }
  797. /**
  798. * Returns string with hidden return tracking form elements.
  799. * @return string
  800. */
  801. public function get_form_fields() {
  802. if (empty($this->type)) {
  803. return '';
  804. }
  805. $result = '<input type="hidden" name="gpr_type" value="'.$this->type.'" />';
  806. if (!empty($this->plugin)) {
  807. $result .= '<input type="hidden" name="gpr_plugin" value="'.$this->plugin.'" />';
  808. }
  809. if (!empty($this->courseid)) {
  810. $result .= '<input type="hidden" name="gpr_courseid" value="'.$this->courseid.'" />';
  811. }
  812. if (!empty($this->userid)) {
  813. $result .= '<input type="hidden" name="gpr_userid" value="'.$this->userid.'" />';
  814. }
  815. if (!empty($this->page)) {
  816. $result .= '<input type="hidden" name="gpr_page" value="'.$this->page.'" />';
  817. }
  818. }
  819. /**
  820. * Add hidden elements into mform
  821. *
  822. * @param object &$mform moodle form object
  823. *
  824. * @return void
  825. */
  826. public function add_mform_elements(&$mform) {
  827. if (empty($this->type)) {
  828. return;
  829. }
  830. $mform->addElement('hidden', 'gpr_type', $this->type);
  831. $mform->setType('gpr_type', PARAM_SAFEDIR);
  832. if (!empty($this->plugin)) {
  833. $mform->addElement('hidden', 'gpr_plugin', $this->plugin);
  834. $mform->setType('gpr_plugin', PARAM_PLUGIN);
  835. }
  836. if (!empty($this->courseid)) {
  837. $mform->addElement('hidden', 'gpr_courseid', $this->courseid);
  838. $mform->setType('gpr_courseid', PARAM_INT);
  839. }
  840. if (!empty($this->userid)) {
  841. $mform->addElement('hidden', 'gpr_userid', $this->userid);
  842. $mform->setType('gpr_userid', PARAM_INT);
  843. }
  844. if (!empty($this->page)) {
  845. $mform->addElement('hidden', 'gpr_page', $this->page);
  846. $mform->setType('gpr_page', PARAM_INT);
  847. }
  848. }
  849. /**
  850. * Add return tracking params into url
  851. *
  852. * @param moodle_url $url A URL
  853. *
  854. * @return string $url with return tracking params
  855. */
  856. public function add_url_params(moodle_url $url) {
  857. if (empty($this->type)) {
  858. return $url;
  859. }
  860. $url->param('gpr_type', $this->type);
  861. if (!empty($this->plugin)) {
  862. $url->param('gpr_plugin', $this->plugin);
  863. }
  864. if (!empty($this->courseid)) {
  865. $url->param('gpr_courseid' ,$this->courseid);
  866. }
  867. if (!empty($this->userid)) {
  868. $url->param('gpr_userid', $this->userid);
  869. }
  870. if (!empty($this->page)) {
  871. $url->param('gpr_page', $this->page);
  872. }
  873. return $url;
  874. }
  875. }
  876. /**
  877. * Function central to gradebook for building and printing the navigation (breadcrumb trail).
  878. *
  879. * @param string $path The path of the calling script (using __FILE__?)
  880. * @param string $pagename The language string to use as the last part of the navigation (non-link)
  881. * @param mixed $id Either a plain integer (assuming the key is 'id') or
  882. * an array of keys and values (e.g courseid => $courseid, itemid...)
  883. *
  884. * @return string
  885. */
  886. function grade_build_nav($path, $pagename=null, $id=null) {
  887. global $CFG, $COURSE, $PAGE;
  888. $strgrades = get_string('grades', 'grades');
  889. // Parse the path and build navlinks from its elements
  890. $dirroot_length = strlen($CFG->dirroot) + 1; // Add 1 for the first slash
  891. $path = substr($path, $dirroot_length);
  892. $path = str_replace('\\', '/', $path);
  893. $path_elements = explode('/', $path);
  894. $path_elements_count = count($path_elements);
  895. // First link is always 'grade'
  896. $PAGE->navbar->add($strgrades, new moodle_url('/grade/index.php', array('id'=>$COURSE->id)));
  897. $link = null;
  898. $numberofelements = 3;
  899. // Prepare URL params string
  900. $linkparams = array();
  901. if (!is_null($id)) {
  902. if (is_array($id)) {
  903. foreach ($id as $idkey => $idvalue) {
  904. $linkparams[$idkey] = $idvalue;
  905. }
  906. } else {
  907. $linkparams['id'] = $id;
  908. }
  909. }
  910. $navlink4 = null;
  911. // Remove file extensions from filenames
  912. foreach ($path_elements as $key => $filename) {
  913. $path_elements[$key] = str_replace('.php', '', $filename);
  914. }
  915. // Second level links
  916. switch ($path_elements[1]) {
  917. case 'edit': // No link
  918. if ($path_elements[3] != 'index.php') {
  919. $numberofelements = 4;
  920. }
  921. break;
  922. case 'import': // No link
  923. break;
  924. case 'export': // No link
  925. break;
  926. case 'report':
  927. // $id is required for this link. Do not print it if $id isn't given
  928. if (!is_null($id)) {
  929. $link = new moodle_url('/grade/report/index.php', $linkparams);
  930. }
  931. if ($path_elements[2] == 'grader') {
  932. $numberofelements = 4;
  933. }
  934. break;
  935. default:
  936. // If this element isn't among the ones already listed above, it isn't supported, throw an error.
  937. debugging("grade_build_nav() doesn't support ". $path_elements[1] .
  938. " as the second path element after 'grade'.");
  939. return false;
  940. }
  941. $PAGE->navbar->add(get_string($path_elements[1], 'grades'), $link);
  942. // Third level links
  943. if (empty($pagename)) {
  944. $pagename = get_string($path_elements[2], 'grades');
  945. }
  946. switch ($numberofelements) {
  947. case 3:
  948. $PAGE->navbar->add($pagename, $link);
  949. break;
  950. case 4:
  951. if ($path_elements[2] == 'grader' AND $path_elements[3] != 'index.php') {
  952. $PAGE->navbar->add(get_string('pluginname', 'gradereport_grader'), new moodle_url('/grade/report/grader/index.php', $linkparams));
  953. }
  954. $PAGE->navbar->add($pagename);
  955. break;
  956. }
  957. return '';
  958. }
  959. /**
  960. * General structure representing grade items in course
  961. *
  962. * @package core_grades
  963. * @copyright 2009 Nicolas Connault
  964. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  965. */
  966. class grade_structure {
  967. public $context;
  968. public $courseid;
  969. /**
  970. * Reference to modinfo for current course (for performance, to save
  971. * retrieving it from courseid every time). Not actually set except for
  972. * the grade_tree type.
  973. * @var course_modinfo
  974. */
  975. public $modinfo;
  976. /**
  977. * 1D array of grade items only
  978. */
  979. public $items;
  980. /**
  981. * Returns icon of element
  982. *
  983. * @param array &$element An array representing an element in the grade_tree
  984. * @param bool $spacerifnone return spacer if no icon found
  985. *
  986. * @return string icon or spacer
  987. */
  988. public function get_element_icon(&$element, $spacerifnone=false) {
  989. global $CFG, $OUTPUT;
  990. require_once $CFG->libdir.'/filelib.php';
  991. switch ($element['type']) {
  992. case 'item':
  993. case 'courseitem':
  994. case 'categoryitem':
  995. $is_course = $element['object']->is_course_item();
  996. $is_category = $element['object']->is_category_item();
  997. $is_scale = $element['object']->gradetype == GRADE_TYPE_SCALE;
  998. $is_value = $element['object']->gradetype == GRADE_TYPE_VALUE;
  999. $is_outcome = !empty($element['object']->outcomeid);
  1000. if ($element['object']->is_calculated()) {
  1001. $strcalc = get_string('calculatedgrade', 'grades');
  1002. return '<img src="'.$OUTPUT->pix_url('i/calc') . '" class="icon itemicon" title="'.
  1003. s($strcalc).'" alt="'.s($strcalc).'"/>';
  1004. } else if (($is_course or $is_category) and ($is_scale or $is_value)) {
  1005. if ($category = $element['object']->get_item_category()) {
  1006. switch ($category->aggregation) {
  1007. case GRADE_AGGREGATE_MEAN:
  1008. case GRADE_AGGREGATE_MEDIAN:
  1009. case GRADE_AGGREGATE_WEIGHTED_MEAN:
  1010. case GRADE_AGGREGATE_WEIGHTED_MEAN2:
  1011. case GRADE_AGGREGATE_EXTRACREDIT_MEAN:
  1012. $stragg = get_string('aggregation', 'grades');
  1013. return '<img src="'.$OUTPUT->pix_url('i/agg_mean') . '" ' .
  1014. 'class="icon itemicon" title="'.s($stragg).'" alt="'.s($stragg).'"/>';
  1015. case GRADE_AGGREGATE_SUM:
  1016. $stragg = get_string('aggregation', 'grades');
  1017. return '<img src="'.$OUTPUT->pix_url('i/agg_sum') . '" ' .
  1018. 'class="icon itemicon" title="'.s($stragg).'" alt="'.s($stragg).'"/>';
  1019. }
  1020. }
  1021. } else if ($element['object']->itemtype == 'mod') {
  1022. //prevent outcomes being displaying the same icon as the activity they are attached to
  1023. if ($is_outcome) {
  1024. $stroutcome = s(get_string('outcome', 'grades'));
  1025. return '<img src="'.$OUTPUT->pix_url('i/outcomes') . '" ' .
  1026. 'class="icon itemicon" title="'.$stroutcome.
  1027. '" alt="'.$stroutcome.'"/>';
  1028. } else {
  1029. $strmodname = get_string('modulename', $element['object']->itemmodule);
  1030. return '<img src="'.$OUTPUT->pix_url('icon',
  1031. $element['object']->itemmodule) . '" ' .
  1032. 'class="icon itemicon" title="' .s($strmodname).
  1033. '" alt="' .s($strmodname).'"/>';
  1034. }
  1035. } else if ($element['object']->itemtype == 'manual') {
  1036. if ($element['object']->is_outcome_item()) {
  1037. $stroutcome = get_string('outcome', 'grades');
  1038. return '<img src="'.$OUTPUT->pix_url('i/outcomes') . '" ' .
  1039. 'class="icon itemicon" title="'.s($stroutcome).
  1040. '" alt="'.s($stroutcome).'"/>';
  1041. } else {
  1042. $strmanual = get_string('manualitem', 'grades');
  1043. return '<img src="'.$OUTPUT->pix_url('i/manual_item') . '" '.
  1044. 'class="icon itemicon" title="'.s($strmanual).
  1045. '" alt="'.s($strmanual).'"/>';
  1046. }
  1047. }
  1048. break;
  1049. case 'category':
  1050. $strcat = get_string('category', 'grades');
  1051. return '<img src="'.$OUTPUT->pix_url('i/folder') . '" class="icon itemicon" ' .
  1052. 'title="'.s($strcat).'" alt="'.s($strcat).'" />';
  1053. }
  1054. if ($spacerifnone) {
  1055. return $OUTPUT->spacer().' ';
  1056. } else {
  1057. return '';
  1058. }
  1059. }
  1060. /**
  1061. * Returns name of element optionally with icon and link
  1062. *
  1063. * @param array &$element An array representing an element in the grade_tree
  1064. * @param bool $withlink Whether or not this header has a link
  1065. * @param bool $icon Whether or not to display an icon with this header
  1066. * @param bool $spacerifnone return spacer if no icon found
  1067. *
  1068. * @return string header
  1069. */
  1070. public function get_element_header(&$element, $withlink=false, $icon=true, $spacerifnone=false) {
  1071. $header = '';
  1072. if ($icon) {
  1073. $header .= $this->get_element_icon($element, $spacerifnone);
  1074. }
  1075. $header .= $element['object']->get_name();
  1076. if ($element['type'] != 'item' and $element['type'] != 'categoryitem' and
  1077. $element['type'] != 'courseitem') {
  1078. return $header;
  1079. }
  1080. if ($withlink) {
  1081. $url = $this->get_activity_link($element);
  1082. if ($url) {
  1083. $a = new stdClass();
  1084. $a->name = get_string('modulename', $element['object']->itemmodule);
  1085. $title = get_string('linktoactivity', 'grades', $a);
  1086. $header = html_writer::link($url, $header, array('title' => $title));
  1087. }
  1088. }
  1089. return $header;
  1090. }
  1091. private function get_activity_link($element) {
  1092. global $CFG;
  1093. /** @var array static cache of the grade.php file existence flags */
  1094. static $hasgradephp = array();
  1095. $itemtype = $element['object']->itemtype;
  1096. $itemmodule = $element['object']->itemmodule;
  1097. $iteminstance = $element['object']->iteminstance;
  1098. $itemnumber = $element['object']->itemnumber;
  1099. // Links only for module items that have valid instance, module and are
  1100. // called from grade_tree with valid modinfo
  1101. if ($itemtype != 'mod' || !$iteminstance || !$itemmodule || !$this->modinfo) {
  1102. return null;
  1103. }
  1104. // Get $cm efficiently and with visibility information using modinfo
  1105. $instances = $this->modinfo->get_instances();
  1106. if (empty($instances[$itemmodule][$iteminstance])) {
  1107. return null;
  1108. }
  1109. $cm = $instances[$itemmodule][$iteminstance];
  1110. // Do not add link if activity is not visible to the current user
  1111. if (!$cm->uservisible) {
  1112. return null;
  1113. }
  1114. if (!array_key_exists($itemmodule, $hasgradephp)) {
  1115. if (file_exists($CFG->dirroot . '/mod/' . $itemmodule . '/grade.php')) {
  1116. $hasgradephp[$itemmodule] = true;
  1117. } else {
  1118. $hasgradephp[$itemmodule] = false;
  1119. }
  1120. }
  1121. // If module has grade.php, link to that, otherwise view.php
  1122. if ($hasgradephp[$itemmodule]) {
  1123. $args = array('id' => $cm->id, 'itemnumber' => $itemnumber);
  1124. if (isset($element['userid'])) {
  1125. $args['userid'] = $element['userid'];
  1126. }
  1127. return new moodle_url('/mod/' . $itemmodule . '/grade.php', $args);
  1128. } else {
  1129. return new moodle_url('/mod/' . $itemmodule . '/view.php', array('id' => $cm->id));
  1130. }
  1131. }
  1132. /**
  1133. * Returns URL of a page that is supposed to contain detailed grade analysis
  1134. *
  1135. * At the moment, only activity modules are supported. The method generates link
  1136. * to the module's file grade.php with the parameters id (cmid), itemid, itemnumber,
  1137. * gradeid and userid. If the grade.php does not exist, null is returned.
  1138. *
  1139. * @return moodle_url|null URL or null if unable to construct it
  1140. */
  1141. public function get_grade_analysis_url(grade_grade $grade) {
  1142. global $CFG;
  1143. /** @var array static cache of the grade.php file existence flags */
  1144. static $hasgradephp = array();
  1145. if (empty($grade->grade_item) or !($grade->grade_item instanceof grade_item)) {
  1146. throw new coding_exception('Passed grade without the associated grade item');
  1147. }
  1148. $item = $grade->grade_item;
  1149. if (!$item->is_external_item()) {
  1150. // at the moment, only activity modules are supported
  1151. return null;
  1152. }
  1153. if ($item->itemtype !== 'mod') {
  1154. throw new coding_exception('Unknown external itemtype: '.$item->itemtype);
  1155. }
  1156. if (empty($item->iteminstance) or empty($item->itemmodule) or empty($this->modinfo)) {
  1157. return null;
  1158. }
  1159. if (!array_key_exists($item->itemmodule, $hasgradephp)) {
  1160. if (file_exists($CFG->dirroot . '/mod/' . $item->itemmodule . '/grade.php')) {
  1161. $hasgradephp[$item->itemmodule] = true;
  1162. } else {
  1163. $hasgradephp[$item->itemmodule] = false;
  1164. }
  1165. }
  1166. if (!$hasgradephp[$item->itemmodule]) {
  1167. return null;
  1168. }
  1169. $instances = $this->modinfo->get_instances();
  1170. if (empty($instances[$item->itemmodule][$item->iteminstance])) {
  1171. return null;
  1172. }
  1173. $cm = $instances[$item->itemmodule][$item->iteminstance];
  1174. if (!$cm->uservisible) {
  1175. return null;
  1176. }
  1177. $url = new moodle_url('/mod/'.$item->itemmodule.'/grade.php', array(
  1178. 'id' => $cm->id,
  1179. 'itemid' => $item->id,
  1180. 'itemnumber' => $item->itemnumber,
  1181. 'gradeid' => $grade->id,
  1182. 'userid' => $grade->userid,
  1183. ));
  1184. return $url;
  1185. }
  1186. /**
  1187. * Returns an action icon leading to the grade analysis page
  1188. *
  1189. * @param grade_grade $grade
  1190. * @return string
  1191. */
  1192. public function get_grade_analysis_icon(grade_grade $grade) {
  1193. global $OUTPUT;
  1194. $url = $this->get_grade_analysis_url($grade);
  1195. if (is_null($url)) {
  1196. return '';
  1197. }
  1198. return $OUTPUT->action_icon($url, new pix_icon('t/preview',
  1199. get_string('gradeanalysis', 'core_grades')));
  1200. }
  1201. /**
  1202. * Returns the grade eid - the grade may not exist yet.
  1203. *
  1204. * @param grade_grade $grade_grade A grade_grade object
  1205. *
  1206. * @return string eid
  1207. */
  1208. public function get_grade_eid($grade_grade) {
  1209. if (empty($grade_grade->id)) {
  1210. return 'n'.$grade_grade->itemid.'u'.$grade_grade->userid;
  1211. } else {
  1212. return 'g'.$grade_grade->id;
  1213. }
  1214. }
  1215. /**
  1216. * Returns the grade_item eid
  1217. * @param grade_item $grade_item A grade_item object
  1218. * @return string eid
  1219. */
  1220. public function get_item_eid($grade_item) {
  1221. return 'i'.$grade_item->id;
  1222. }
  1223. /**
  1224. * Given a grade_tree element, returns an array of parameters
  1225. * used to build an icon for that element.
  1226. *
  1227. * @param array $element An array representing an element in the grade_tree
  1228. *
  1229. * @return array
  1230. */
  1231. public function get_params_for_iconstr($element) {
  1232. $strparams = new stdClass();
  1233. $strparams->category = '';
  1234. $strparams->itemname = '';
  1235. $strparams->itemmodule = '';
  1236. if (!method_exists($element['object'], 'get_name')) {
  1237. return $strparams;
  1238. }
  1239. $strparams->itemname = html_to_text($element['object']->get_name());
  1240. // If element name is categorytotal, get the name of the parent category
  1241. if ($strparams->itemname == get_string('categorytotal', 'grades')) {
  1242. $parent = $element['object']->get_parent_category();
  1243. $strparams->category = $parent->get_name() . ' ';
  1244. } else {
  1245. $strparams->category = '';
  1246. }
  1247. $strparams->itemmodule = null;
  1248. if (isset($element['object']->itemmodule)) {
  1249. $strparams->itemmodule = $element['object']->itemmodule;
  1250. }
  1251. return $strparams;
  1252. }
  1253. /**
  1254. * Return edit icon for give element
  1255. *
  1256. * @param array $element An array represen…

Large files files are truncated, but you can click here to view the full file