MDL-64993 core_message: Add self-conversations to create_user generator
[moodle.git] / lib / grade / grade_outcome.php
blob064cdd160cb668587243e1950e821bbcb47da1f3
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.
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/>.
17 /**
18 * Definition of grade outcome class
20 * @package core_grades
21 * @category grade
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');
30 /**
31 * Class representing a grade outcome.
33 * It is responsible for handling its DB representation, modifying and returning its metadata.
35 * @package core_grades
36 * @category grade
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 {
41 /**
42 * DB Table (used by grade_object).
43 * @var string $table
45 public $table = 'grade_outcomes';
47 /**
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');
54 /**
55 * The course this outcome belongs to.
56 * @var int $courseid
58 public $courseid;
60 /**
61 * The shortname of the outcome.
62 * @var string $shortname
64 public $shortname;
66 /**
67 * The fullname of the outcome.
68 * @var string $fullname
70 public $fullname;
72 /**
73 * A full grade_scale object referenced by $this->scaleid.
74 * @var object $scale
76 public $scale;
78 /**
79 * The id of the scale referenced by this outcome.
80 * @var int $scaleid
82 public $scaleid;
84 /**
85 * The description of this outcome - FORMAT_MOODLE.
86 * @var string $description
88 public $description;
90 /**
91 * The userid of the person who last modified this outcome.
93 * @var int $usermodified
95 public $usermodified;
97 /**
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) {
104 global $DB;
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) {
113 $file->delete();
115 return true;
117 return false;
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) {
129 global $DB;
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);
141 return $result;
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);
158 return $result;
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) {
168 global $DB;
169 if (!empty($this->courseid) and $courseid != $this->courseid) {
170 return false;
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);
179 return true;
183 * Finds and returns a grade_outcome instance based on params.
185 * @static
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.
196 * @static
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();
214 return $this->scale;
218 * Static function returning all global outcomes
220 * @static
221 * @return array
223 public static function fetch_all_global() {
224 if (!$outcomes = grade_outcome::fetch_all(array('courseid'=>null))) {
225 $outcomes = array();
227 return $outcomes;
231 * Static function returning all local course outcomes
233 * @static
234 * @param int $courseid
235 * @return array
237 public static function fetch_all_local($courseid) {
238 if (!$outcomes =grade_outcome::fetch_all(array('courseid'=>$courseid))) {
239 $outcomes = array();
241 return $outcomes;
245 * Static method that returns all outcomes available in course
247 * @static
248 * @param int $courseid
249 * @return array
251 public static function fetch_all_available($courseid) {
252 global $CFG, $DB;
254 $result = array();
255 $params = array($courseid);
256 $sql = "SELECT go.*
257 FROM {grade_outcomes} go, {grade_outcomes_courses} goc
258 WHERE go.id = goc.outcomeid AND goc.courseid = ?
259 ORDER BY go.id ASC";
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;
268 return $result;
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
296 * @return string
298 public function get_description() {
299 global $CFG;
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.
312 * @return bool
314 public function can_delete() {
315 if ($this->get_item_uses_count()) {
316 return false;
318 if (empty($this->courseid)) {
319 if ($this->get_course_uses_count()) {
320 return false;
323 return true;
327 * Returns the number of places where outcome is used.
329 * @return int
331 public function get_course_uses_count() {
332 global $DB;
334 if (!empty($this->courseid)) {
335 return 1;
338 return $DB->count_records('grade_outcomes_courses', array('outcomeid' => $this->id));
342 * Returns the number of grade items that use this grade outcome
344 * @return int
346 public function get_item_uses_count() {
347 global $DB;
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
362 * @return float
364 public function get_grade_info($courseid=null, $average=true, $items=false) {
365 global $CFG, $DB;
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!');
374 return false;
377 $params = array($this->id);
379 $wheresql = '';
380 if (!is_null($courseid)) {
381 $wheresql = " AND {grade_items}.courseid = ? ";
382 $params[] = $courseid;
385 $selectadd = '';
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 = ?
395 $wheresql";
397 $grades = $DB->get_records_sql($sql, $params);
398 $retval = array();
400 if ($average !== false && count($grades) > 0) {
401 $count = 0;
402 $total = 0;
404 foreach ($grades as $k => $grade) {
405 // Skip null finalgrades
406 if (!is_null($grade->finalgrade)) {
407 $total += $grade->finalgrade;
408 $count++;
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);
422 return $retval;