2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Definition of grade outcome class
20 * @package core_grades
22 * @copyright 2006 Nicolas Connault
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
28 require_once('grade_object.php');
31 * Class representing a grade outcome.
33 * It is responsible for handling its DB representation, modifying and returning its metadata.
35 * @package core_grades
37 * @copyright 2006 Nicolas Connault
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 class grade_outcome
extends grade_object
{
42 * DB Table (used by grade_object).
45 public $table = 'grade_outcomes';
48 * Array of required table fields, must start with 'id'.
49 * @var array $required_fields
51 public $required_fields = array('id', 'courseid', 'shortname', 'fullname', 'scaleid','description',
52 'descriptionformat', 'timecreated', 'timemodified', 'usermodified');
55 * The course this outcome belongs to.
61 * The shortname of the outcome.
62 * @var string $shortname
67 * The fullname of the outcome.
68 * @var string $fullname
73 * A full grade_scale object referenced by $this->scaleid.
79 * The id of the scale referenced by this outcome.
85 * The description of this outcome - FORMAT_MOODLE.
86 * @var string $description
91 * The userid of the person who last modified this outcome.
93 * @var int $usermodified
98 * Deletes this outcome from the database.
100 * @param string $source from where was the object deleted (mod/forum, manual, etc.)
101 * @return bool success
103 public function delete($source=null) {
105 if (!empty($this->courseid
)) {
106 $DB->delete_records('grade_outcomes_courses', array('outcomeid' => $this->id
, 'courseid' => $this->courseid
));
108 if (parent
::delete($source)) {
109 $context = context_system
::instance();
110 $fs = get_file_storage();
111 $files = $fs->get_area_files($context->id
, 'grade', 'outcome', $this->id
);
112 foreach ($files as $file) {
121 * Records this object in the Database, sets its id to the returned value, and returns that value.
122 * If successful this function also fetches the new object data from database and stores it
123 * in object properties.
125 * @param string $source from where was the object inserted (mod/forum, manual, etc.)
126 * @return int PK ID if successful, false otherwise
128 public function insert($source=null) {
131 $this->timecreated
= $this->timemodified
= time();
133 if ($result = parent
::insert($source)) {
134 if (!empty($this->courseid
)) {
135 $goc = new stdClass();
136 $goc->courseid
= $this->courseid
;
137 $goc->outcomeid
= $this->id
;
138 $DB->insert_record('grade_outcomes_courses', $goc);
145 * In addition to update() it also updates grade_outcomes_courses if needed
147 * @param string $source from where was the object inserted
148 * @return bool success
150 public function update($source=null) {
151 $this->timemodified
= time();
153 if ($result = parent
::update($source)) {
154 if (!empty($this->courseid
)) {
155 $this->use_in($this->courseid
);
162 * Mark outcome as used in a course
164 * @param int $courseid
165 * @return False if invalid courseid requested
167 public function use_in($courseid) {
169 if (!empty($this->courseid
) and $courseid != $this->courseid
) {
173 if (!$DB->record_exists('grade_outcomes_courses', array('courseid' => $courseid, 'outcomeid' => $this->id
))) {
174 $goc = new stdClass();
175 $goc->courseid
= $courseid;
176 $goc->outcomeid
= $this->id
;
177 $DB->insert_record('grade_outcomes_courses', $goc);
183 * Finds and returns a grade_outcome instance based on params.
186 * @param array $params associative arrays varname=>value
187 * @return object grade_outcome instance or false if none found.
189 public static function fetch($params) {
190 return grade_object
::fetch_helper('grade_outcomes', 'grade_outcome', $params);
194 * Finds and returns all grade_outcome instances based on params.
197 * @param array $params associative arrays varname=>value
198 * @return array array of grade_outcome insatnces or false if none found.
200 public static function fetch_all($params) {
201 return grade_object
::fetch_all_helper('grade_outcomes', 'grade_outcome', $params);
205 * Instantiates a grade_scale object whose data is retrieved from the database
207 * @return grade_scale
209 public function load_scale() {
210 if (empty($this->scale
->id
) or $this->scale
->id
!= $this->scaleid
) {
211 $this->scale
= grade_scale
::fetch(array('id'=>$this->scaleid
));
212 $this->scale
->load_items();
218 * Static function returning all global outcomes
223 public static function fetch_all_global() {
224 if (!$outcomes = grade_outcome
::fetch_all(array('courseid'=>null))) {
231 * Static function returning all local course outcomes
234 * @param int $courseid
237 public static function fetch_all_local($courseid) {
238 if (!$outcomes =grade_outcome
::fetch_all(array('courseid'=>$courseid))) {
245 * Static method that returns all outcomes available in course
248 * @param int $courseid
251 public static function fetch_all_available($courseid) {
255 $params = array($courseid);
257 FROM {grade_outcomes} go, {grade_outcomes_courses} goc
258 WHERE go.id = goc.outcomeid AND goc.courseid = ?
261 if ($datas = $DB->get_records_sql($sql, $params)) {
262 foreach($datas as $data) {
263 $instance = new grade_outcome();
264 grade_object
::set_properties($instance, $data);
265 $result[$instance->id
] = $instance;
273 * Returns the most descriptive field for this object. This is a standard method used
274 * when we do not know the exact type of an object.
276 * @return string name
278 public function get_name() {
279 // Grade outcomes can be created at site or course context, so set the filter context appropriately.
280 $context = empty($this->courseid
) ? context_system
::instance() : context_course
::instance($this->courseid
);
281 return format_string($this->fullname
, false, ["context" => $context]);
285 * Returns unique outcome short name.
287 * @return string name
289 public function get_shortname() {
290 return $this->shortname
;
294 * Returns the formatted grade description with URLs converted
298 public function get_description() {
300 require_once($CFG->libdir
. '/filelib.php');
302 $options = new stdClass
;
303 $options->noclean
= true;
304 $systemcontext = context_system
::instance();
305 $description = file_rewrite_pluginfile_urls($this->description
, 'pluginfile.php', $systemcontext->id
, 'grade', 'outcome', $this->id
);
306 return format_text($description, $this->descriptionformat
, $options);
310 * Checks if outcome can be deleted.
314 public function can_delete() {
315 if ($this->get_item_uses_count()) {
318 if (empty($this->courseid
)) {
319 if ($this->get_course_uses_count()) {
327 * Returns the number of places where outcome is used.
331 public function get_course_uses_count() {
334 if (!empty($this->courseid
)) {
338 return $DB->count_records('grade_outcomes_courses', array('outcomeid' => $this->id
));
342 * Returns the number of grade items that use this grade outcome
346 public function get_item_uses_count() {
348 return $DB->count_records('grade_items', array('outcomeid' => $this->id
));
352 * Computes then returns extra information about this outcome and other objects that are linked to it.
353 * The average of all grades that use this outcome, for all courses (or 1 course if courseid is given) can
354 * be requested, and is returned as a float if requested alone. If the list of items that use this outcome
355 * is also requested, then a single array is returned, which contains the grade_items AND the average grade
356 * if such is still requested (array('items' => array(...), 'avg' => 2.30)). This combining of two
357 * methods into one is to save on DB queries, since both queries are similar and can be performed together.
359 * @param int $courseid An optional courseid to narrow down the average to 1 course only
360 * @param bool $average Whether or not to return the average grade for this outcome
361 * @param bool $items Whether or not to return the list of items using this outcome
364 public function get_grade_info($courseid=null, $average=true, $items=false) {
367 if (!isset($this->id
)) {
368 debugging("You must setup the outcome's id before calling its get_grade_info() method!");
369 return false; // id must be defined for this to work
372 if ($average === false && $items === false) {
373 debugging('Either the 1st or 2nd param of grade_outcome::get_grade_info() must be true, or both, but not both false!');
377 $params = array($this->id
);
380 if (!is_null($courseid)) {
381 $wheresql = " AND {grade_items}.courseid = ? ";
382 $params[] = $courseid;
386 if ($items !== false) {
387 $selectadd = ", {grade_items}.* ";
390 $sql = "SELECT finalgrade $selectadd
391 FROM {grade_grades}, {grade_items}, {grade_outcomes}
392 WHERE {grade_outcomes}.id = {grade_items}.outcomeid
393 AND {grade_items}.id = {grade_grades}.itemid
394 AND {grade_outcomes}.id = ?
397 $grades = $DB->get_records_sql($sql, $params);
400 if ($average !== false && count($grades) > 0) {
404 foreach ($grades as $k => $grade) {
405 // Skip null finalgrades
406 if (!is_null($grade->finalgrade
)) {
407 $total +
= $grade->finalgrade
;
410 unset($grades[$k]->finalgrade
);
413 $retval['avg'] = $total / $count;
416 if ($items !== false) {
417 foreach ($grades as $grade) {
418 $retval['items'][$grade->id
] = new grade_item($grade);