PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/grade/report/lib.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 422 lines | 188 code | 59 blank | 175 comment | 38 complexity | ccd5dbe49059408e5572c303ed460549 MD5 | raw 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. * File containing the grade_report class
  18. *
  19. * @package core_grades
  20. * @copyright 2007 Moodle Pty Ltd (http://moodle.com)
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. require_once($CFG->libdir.'/gradelib.php');
  24. /**
  25. * An abstract class containing variables and methods used by all or most reports.
  26. * @package core_grades
  27. */
  28. abstract class grade_report {
  29. /**
  30. * The courseid.
  31. * @var int $courseid
  32. */
  33. public $courseid;
  34. /**
  35. * The course.
  36. * @var object $course
  37. */
  38. public $course;
  39. /** Grade plugin return tracking object.
  40. * @var object $gpr
  41. */
  42. public $gpr;
  43. /**
  44. * The context.
  45. * @var int $context
  46. */
  47. public $context;
  48. /**
  49. * The grade_tree object.
  50. * @var object $gtree
  51. */
  52. public $gtree;
  53. /**
  54. * User preferences related to this report.
  55. * @var array $prefs
  56. */
  57. public $prefs = array();
  58. /**
  59. * The roles for this report.
  60. * @var string $gradebookroles
  61. */
  62. public $gradebookroles;
  63. /**
  64. * base url for sorting by first/last name.
  65. * @var string $baseurl
  66. */
  67. public $baseurl;
  68. /**
  69. * base url for paging.
  70. * @var string $pbarurl
  71. */
  72. public $pbarurl;
  73. /**
  74. * Current page (for paging).
  75. * @var int $page
  76. */
  77. public $page;
  78. /**
  79. * Array of cached language strings (using get_string() all the time takes a long time!).
  80. * @var array $lang_strings
  81. */
  82. public $lang_strings = array();
  83. //// GROUP VARIABLES (including SQL)
  84. /**
  85. * The current group being displayed.
  86. * @var int $currentgroup
  87. */
  88. public $currentgroup;
  89. /**
  90. * Current course group mode
  91. * @var int $groupmode
  92. */
  93. var $groupmode;
  94. /**
  95. * A HTML select element used to select the current group.
  96. * @var string $group_selector
  97. */
  98. public $group_selector;
  99. /**
  100. * An SQL fragment used to add linking information to the group tables.
  101. * @var string $groupsql
  102. */
  103. protected $groupsql;
  104. /**
  105. * An SQL constraint to append to the queries used by this object to build the report.
  106. * @var string $groupwheresql
  107. */
  108. protected $groupwheresql;
  109. /**
  110. * The ordered params for $groupwheresql
  111. * @var array $groupwheresql_params
  112. */
  113. protected $groupwheresql_params = array();
  114. /**
  115. * Constructor. Sets local copies of user preferences and initialises grade_tree.
  116. * @param int $courseid
  117. * @param object $gpr grade plugin return tracking object
  118. * @param string $context
  119. * @param int $page The current page being viewed (when report is paged)
  120. */
  121. public function __construct($courseid, $gpr, $context, $page=null) {
  122. global $CFG, $COURSE, $DB;
  123. if (empty($CFG->gradebookroles)) {
  124. print_error('norolesdefined', 'grades');
  125. }
  126. $this->courseid = $courseid;
  127. if ($this->courseid == $COURSE->id) {
  128. $this->course = $COURSE;
  129. } else {
  130. $this->course = $DB->get_record('course', array('id' => $this->courseid));
  131. }
  132. $this->gpr = $gpr;
  133. $this->context = $context;
  134. $this->page = $page;
  135. // roles to be displayed in the gradebook
  136. $this->gradebookroles = $CFG->gradebookroles;
  137. // Set up link to preferences page
  138. $this->preferences_page = $CFG->wwwroot.'/grade/report/grader/preferences.php?id='.$courseid;
  139. // init gtree in child class
  140. }
  141. /**
  142. * Given the name of a user preference (without grade_report_ prefix), locally saves then returns
  143. * the value of that preference. If the preference has already been fetched before,
  144. * the saved value is returned. If the preference is not set at the User level, the $CFG equivalent
  145. * is given (site default).
  146. * @static (Can be called statically, but then doesn't benefit from caching)
  147. * @param string $pref The name of the preference (do not include the grade_report_ prefix)
  148. * @param int $objectid An optional itemid or categoryid to check for a more fine-grained preference
  149. * @return mixed The value of the preference
  150. */
  151. public function get_pref($pref, $objectid=null) {
  152. global $CFG;
  153. $fullprefname = 'grade_report_' . $pref;
  154. $shortprefname = 'grade_' . $pref;
  155. $retval = null;
  156. if (!isset($this) OR get_class($this) != 'grade_report') {
  157. if (!empty($objectid)) {
  158. $retval = get_user_preferences($fullprefname . $objectid, grade_report::get_pref($pref));
  159. } elseif (isset($CFG->$fullprefname)) {
  160. $retval = get_user_preferences($fullprefname, $CFG->$fullprefname);
  161. } elseif (isset($CFG->$shortprefname)) {
  162. $retval = get_user_preferences($fullprefname, $CFG->$shortprefname);
  163. } else {
  164. $retval = null;
  165. }
  166. } else {
  167. if (empty($this->prefs[$pref.$objectid])) {
  168. if (!empty($objectid)) {
  169. $retval = get_user_preferences($fullprefname . $objectid);
  170. if (empty($retval)) {
  171. // No item pref found, we are returning the global preference
  172. $retval = $this->get_pref($pref);
  173. $objectid = null;
  174. }
  175. } else {
  176. $retval = get_user_preferences($fullprefname, $CFG->$fullprefname);
  177. }
  178. $this->prefs[$pref.$objectid] = $retval;
  179. } else {
  180. $retval = $this->prefs[$pref.$objectid];
  181. }
  182. }
  183. return $retval;
  184. }
  185. /**
  186. * Uses set_user_preferences() to update the value of a user preference. If 'default' is given as the value,
  187. * the preference will be removed in favour of a higher-level preference.
  188. * @static
  189. * @param string $pref_name The name of the preference.
  190. * @param mixed $pref_value The value of the preference.
  191. * @param int $itemid An optional itemid to which the preference will be assigned
  192. * @return bool Success or failure.
  193. */
  194. public function set_pref($pref, $pref_value='default', $itemid=null) {
  195. $fullprefname = 'grade_report_' . $pref;
  196. if ($pref_value == 'default') {
  197. return unset_user_preference($fullprefname.$itemid);
  198. } else {
  199. return set_user_preference($fullprefname.$itemid, $pref_value);
  200. }
  201. }
  202. /**
  203. * Handles form data sent by this report for this report. Abstract method to implement in all children.
  204. * @abstract
  205. * @param array $data
  206. * @return mixed True or array of errors
  207. */
  208. abstract function process_data($data);
  209. /**
  210. * Processes a single action against a category, grade_item or grade.
  211. * @param string $target Sortorder
  212. * @param string $action Which action to take (edit, delete etc...)
  213. * @return
  214. */
  215. abstract function process_action($target, $action);
  216. /**
  217. * First checks the cached language strings, then returns match if found, or uses get_string()
  218. * to get it from the DB, caches it then returns it.
  219. * @param string $strcode
  220. * @param string $section Optional language section
  221. * @return string
  222. */
  223. public function get_lang_string($strcode, $section=null) {
  224. if (empty($this->lang_strings[$strcode])) {
  225. $this->lang_strings[$strcode] = get_string($strcode, $section);
  226. }
  227. return $this->lang_strings[$strcode];
  228. }
  229. /**
  230. * Fetches and returns a count of all the users that will be shown on this page.
  231. * @param boolean $groups include groups limit
  232. * @return int Count of users
  233. */
  234. public function get_numusers($groups=true) {
  235. global $CFG, $DB;
  236. $groupsql = "";
  237. $groupwheresql = "";
  238. //limit to users with a gradeable role
  239. list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
  240. //limit to users with an active enrollment
  241. list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
  242. $params = array_merge($gradebookrolesparams, $enrolledparams);
  243. if ($groups) {
  244. $groupsql = $this->groupsql;
  245. $groupwheresql = $this->groupwheresql;
  246. $params = array_merge($params, $this->groupwheresql_params);
  247. }
  248. $countsql = "SELECT COUNT(DISTINCT u.id)
  249. FROM {user} u
  250. JOIN ($enrolledsql) je
  251. ON je.id = u.id
  252. JOIN {role_assignments} ra
  253. ON u.id = ra.userid
  254. $groupsql
  255. WHERE ra.roleid $gradebookrolessql
  256. AND u.deleted = 0
  257. $groupwheresql
  258. AND ra.contextid ".get_related_contexts_string($this->context);
  259. return $DB->count_records_sql($countsql, $params);
  260. }
  261. /**
  262. * Sets up this object's group variables, mainly to restrict the selection of users to display.
  263. */
  264. protected function setup_groups() {
  265. /// find out current groups mode
  266. if ($this->groupmode = groups_get_course_groupmode($this->course)) {
  267. $this->currentgroup = groups_get_course_group($this->course, true);
  268. $this->group_selector = groups_print_course_menu($this->course, $this->pbarurl, true);
  269. if ($this->groupmode == SEPARATEGROUPS and !$this->currentgroup and !has_capability('moodle/site:accessallgroups', $this->context)) {
  270. $this->currentgroup = -2; // means can not access any groups at all
  271. }
  272. if ($this->currentgroup) {
  273. $this->groupsql = " JOIN {groups_members} gm ON gm.userid = u.id ";
  274. $this->groupwheresql = " AND gm.groupid = :gr_grpid ";
  275. $this->groupwheresql_params = array('gr_grpid'=>$this->currentgroup);
  276. }
  277. }
  278. }
  279. /**
  280. * Returns an arrow icon inside an <a> tag, for the purpose of sorting a column.
  281. * @param string $direction
  282. * @param moodle_url $sort_link
  283. * @param string HTML
  284. */
  285. protected function get_sort_arrow($direction='move', $sortlink=null) {
  286. global $OUTPUT;
  287. $pix = array('up' => 't/sort_desc', 'down' => 't/sort_asc', 'move' => 't/sort');
  288. $matrix = array('up' => 'desc', 'down' => 'asc', 'move' => 'desc');
  289. $strsort = $this->get_lang_string('sort' . $matrix[$direction]);
  290. $arrow = $OUTPUT->pix_icon($pix[$direction], $strsort, '', array('class' => 'sorticon'));
  291. return html_writer::link($sortlink, $arrow, array('title'=>$strsort));
  292. }
  293. /**
  294. * Optionally blank out course/category totals if they contain any hidden items
  295. * @param string $courseid the course id
  296. * @param string $course_item an instance of grade_item
  297. * @param string $finalgrade the grade for the course_item
  298. * @return string The new final grade
  299. */
  300. protected function blank_hidden_total($courseid, $course_item, $finalgrade) {
  301. global $CFG, $DB;
  302. static $hiding_affected = null;//array of items in this course affected by hiding
  303. // If we're dealing with multiple users we need to know when we've moved on to a new user.
  304. static $previous_userid = null;
  305. // If we're dealing with multiple courses we need to know when we've moved on to a new course.
  306. static $previous_courseid = null;
  307. if( $this->showtotalsifcontainhidden==GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN ) {
  308. return $finalgrade;
  309. }
  310. // If we've moved on to another course or user, reload the grades.
  311. if ($previous_userid != $this->user->id || $previous_courseid != $courseid) {
  312. $hiding_affected = null;
  313. $previous_userid = $this->user->id;
  314. $previous_courseid = $courseid;
  315. }
  316. if( !$hiding_affected ) {
  317. $items = grade_item::fetch_all(array('courseid'=>$courseid));
  318. $grades = array();
  319. $sql = "SELECT g.*
  320. FROM {grade_grades} g
  321. JOIN {grade_items} gi ON gi.id = g.itemid
  322. WHERE g.userid = {$this->user->id} AND gi.courseid = {$courseid}";
  323. if ($gradesrecords = $DB->get_records_sql($sql)) {
  324. foreach ($gradesrecords as $grade) {
  325. $grades[$grade->itemid] = new grade_grade($grade, false);
  326. }
  327. unset($gradesrecords);
  328. }
  329. foreach ($items as $itemid=>$unused) {
  330. if (!isset($grades[$itemid])) {
  331. $grade_grade = new grade_grade();
  332. $grade_grade->userid = $this->user->id;
  333. $grade_grade->itemid = $items[$itemid]->id;
  334. $grades[$itemid] = $grade_grade;
  335. }
  336. $grades[$itemid]->grade_item =& $items[$itemid];
  337. }
  338. $hiding_affected = grade_grade::get_hiding_affected($grades, $items);
  339. }
  340. //if the item definitely depends on a hidden item
  341. if (array_key_exists($course_item->id, $hiding_affected['altered'])) {
  342. if( !$this->showtotalsifcontainhidden ) {
  343. //hide the grade
  344. $finalgrade = null;
  345. }
  346. else {
  347. //use reprocessed marks that exclude hidden items
  348. $finalgrade = $hiding_affected['altered'][$course_item->id];
  349. }
  350. } else if (!empty($hiding_affected['unknown'][$course_item->id])) {
  351. //not sure whether or not this item depends on a hidden item
  352. if( !$this->showtotalsifcontainhidden ) {
  353. //hide the grade
  354. $finalgrade = null;
  355. }
  356. else {
  357. //use reprocessed marks that exclude hidden items
  358. $finalgrade = $hiding_affected['unknown'][$course_item->id];
  359. }
  360. }
  361. return $finalgrade;
  362. }
  363. }