PageRenderTime 43ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/grade/grade_scale.php

https://gitlab.com/unofficial-mirrors/moodle
PHP | 388 lines | 171 code | 40 blank | 177 comment | 29 complexity | 5ec1cd32c1e03a372b49b1afd25ac17b 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. * Definition of grade scale class
  18. *
  19. * @package core_grades
  20. * @category grade
  21. * @copyright 2006 Nicolas Connault
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. require_once('grade_object.php');
  26. /**
  27. * Class representing a grade scale.
  28. *
  29. * It is responsible for handling its DB representation, modifying and returning its metadata.
  30. *
  31. * @package core_grades
  32. * @category grade
  33. * @copyright 2006 Nicolas Connault
  34. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35. */
  36. class grade_scale extends grade_object {
  37. /**
  38. * DB Table (used by grade_object).
  39. * @var string $table
  40. */
  41. public $table = 'scale';
  42. /**
  43. * Array of required table fields, must start with 'id'.
  44. * @var array $required_fields
  45. */
  46. public $required_fields = array('id', 'courseid', 'userid', 'name', 'scale', 'description', 'descriptionformat', 'timemodified');
  47. /**
  48. * The course this scale belongs to.
  49. * @var int $courseid
  50. */
  51. public $courseid;
  52. /**
  53. * The ID of the user who created the scale
  54. * @var int $userid
  55. */
  56. public $userid;
  57. /**
  58. * The name of the scale.
  59. * @var string $name
  60. */
  61. public $name;
  62. /**
  63. * The items in this scale.
  64. * @var array $scale_items
  65. */
  66. public $scale_items = array();
  67. /**
  68. * A string representation of the scale items (a comma-separated list).
  69. * @var string $scale
  70. */
  71. public $scale;
  72. /**
  73. * A description for this scale.
  74. * @var string $description
  75. */
  76. public $description;
  77. /**
  78. * Finds and returns a grade_scale instance based on params.
  79. *
  80. * @static
  81. * @param array $params associative arrays varname=>value
  82. * @return object grade_scale instance or false if none found.
  83. */
  84. public static function fetch($params) {
  85. return grade_object::fetch_helper('scale', 'grade_scale', $params);
  86. }
  87. /**
  88. * Finds and returns all grade_scale instances based on params.
  89. *
  90. * @static
  91. * @param array $params associative arrays varname=>value
  92. * @return array array of grade_scale instances or false if none found.
  93. */
  94. public static function fetch_all($params) {
  95. return grade_object::fetch_all_helper('scale', 'grade_scale', $params);
  96. }
  97. /**
  98. * Records this object in the Database, sets its id to the returned value, and returns that value.
  99. * If successful this function also fetches the new object data from database and stores it
  100. * in object properties.
  101. *
  102. * @param string $source from where was the object inserted (mod/forum, manual, etc.)
  103. * @return int PK ID if successful, false otherwise
  104. */
  105. public function insert($source=null) {
  106. $this->timecreated = time();
  107. $this->timemodified = time();
  108. $result = parent::insert($source);
  109. if ($result) {
  110. // Trigger the scale created event.
  111. if (!empty($this->standard)) {
  112. $eventcontext = context_system::instance();
  113. } else {
  114. if (!empty($this->courseid)) {
  115. $eventcontext = context_course::instance($this->courseid);
  116. } else {
  117. $eventcontext = context_system::instance();
  118. }
  119. }
  120. $event = \core\event\scale_created::create(array(
  121. 'objectid' => $result,
  122. 'context' => $eventcontext
  123. ));
  124. $event->trigger();
  125. }
  126. return $result;
  127. }
  128. /**
  129. * In addition to update() it also updates grade_outcomes_courses if needed
  130. *
  131. * @param string $source from where was the object inserted
  132. * @return bool success
  133. */
  134. public function update($source=null) {
  135. $this->timemodified = time();
  136. $result = parent::update($source);
  137. if ($result) {
  138. // Trigger the scale updated event.
  139. if (!empty($this->standard)) {
  140. $eventcontext = context_system::instance();
  141. } else {
  142. if (!empty($this->courseid)) {
  143. $eventcontext = context_course::instance($this->courseid);
  144. } else {
  145. $eventcontext = context_system::instance();
  146. }
  147. }
  148. $event = \core\event\scale_updated::create(array(
  149. 'objectid' => $this->id,
  150. 'context' => $eventcontext
  151. ));
  152. $event->trigger();
  153. }
  154. return $result;
  155. }
  156. /**
  157. * Deletes this scale from the database.
  158. *
  159. * @param string $source from where was the object deleted (mod/forum, manual, etc.)
  160. * @return bool success
  161. */
  162. public function delete($source=null) {
  163. global $DB;
  164. // Trigger the scale deleted event.
  165. if (!empty($this->standard)) {
  166. $eventcontext = context_system::instance();
  167. } else {
  168. if (!empty($this->courseid)) {
  169. $eventcontext = context_course::instance($this->courseid);
  170. } else {
  171. $eventcontext = context_system::instance();
  172. }
  173. }
  174. $event = \core\event\scale_deleted::create(array(
  175. 'objectid' => $this->id,
  176. 'context' => $eventcontext
  177. ));
  178. $event->trigger();
  179. if (parent::delete($source)) {
  180. $context = context_system::instance();
  181. $fs = get_file_storage();
  182. $files = $fs->get_area_files($context->id, 'grade', 'scale', $this->id);
  183. foreach ($files as $file) {
  184. $file->delete();
  185. }
  186. return true;
  187. }
  188. return false;
  189. }
  190. /**
  191. * Returns the most descriptive field for this object. This is a standard method used
  192. * when we do not know the exact type of an object.
  193. *
  194. * @return string name
  195. */
  196. public function get_name() {
  197. return format_string($this->name);
  198. }
  199. /**
  200. * Loads the scale's items into the $scale_items array.
  201. * There are three ways to achieve this:
  202. * 1. No argument given: The $scale string is already loaded and exploded to an array of items.
  203. * 2. A string is given: A comma-separated list of items is exploded into an array of items.
  204. * 3. An array of items is given and saved directly as the array of items for this scale.
  205. *
  206. * @param mixed $items Could be null, a string or an array. The method behaves differently for each case.
  207. * @return array The resulting array of scale items or null if the method failed to produce one.
  208. */
  209. public function load_items($items=NULL) {
  210. if (empty($items)) {
  211. $this->scale_items = explode(',', $this->scale);
  212. } elseif (is_array($items)) {
  213. $this->scale_items = $items;
  214. } else {
  215. $this->scale_items = explode(',', $items);
  216. }
  217. // Trim whitespace around each value
  218. foreach ($this->scale_items as $key => $val) {
  219. $this->scale_items[$key] = trim($val);
  220. }
  221. return $this->scale_items;
  222. }
  223. /**
  224. * Compacts (implodes) the array of items in $scale_items into a comma-separated string, $scale.
  225. * There are three ways to achieve this:
  226. * 1. No argument given: The $scale_items array is already loaded and imploded to a string of items.
  227. * 2. An array is given and is imploded into a string of items.
  228. * 3. A string of items is given and saved directly as the $scale variable.
  229. * NOTE: This method is the exact reverse of load_items, and their input/output should be interchangeable. However,
  230. * because load_items() trims the whitespace around the items, when the string is reconstructed these whitespaces will
  231. * be missing. This is not an issue, but should be kept in mind when comparing the two strings.
  232. *
  233. * @param mixed $items Could be null, a string or an array. The method behaves differently for each case.
  234. * @return array The resulting string of scale items or null if the method failed to produce one.
  235. */
  236. public function compact_items($items=NULL) {
  237. if (empty($items)) {
  238. $this->scale = implode(',', $this->scale_items);
  239. } elseif (is_array($items)) {
  240. $this->scale = implode(',', $items);
  241. } else {
  242. $this->scale = $items;
  243. }
  244. return $this->scale;
  245. }
  246. /**
  247. * When called on a loaded scale object (with a valid id) and given a float grade between
  248. * the grademin and grademax, this method returns the scale item that falls closest to the
  249. * float given (which is usually an average of several grades on a scale). If the float falls
  250. * below 1 but above 0, it will be rounded up to 1.
  251. *
  252. * @param float $grade
  253. * @return string
  254. */
  255. public function get_nearest_item($grade) {
  256. global $DB;
  257. // Obtain nearest scale item from average
  258. $scales_array = $DB->get_records('scale', array('id' => $this->id));
  259. $scale = $scales_array[$this->id];
  260. $scales = explode(",", $scale->scale);
  261. // this could be a 0 when summed and rounded, e.g, 1, no grade, no grade, no grade
  262. if ($grade < 1) {
  263. $grade = 1;
  264. }
  265. return $scales[$grade-1];
  266. }
  267. /**
  268. * Static function returning all global scales
  269. *
  270. * @return object
  271. */
  272. public static function fetch_all_global() {
  273. return grade_scale::fetch_all(array('courseid'=>0));
  274. }
  275. /**
  276. * Static function returning all local course scales
  277. *
  278. * @param int $courseid The course ID
  279. * @return array Returns an array of grade_scale instances
  280. */
  281. public static function fetch_all_local($courseid) {
  282. return grade_scale::fetch_all(array('courseid'=>$courseid));
  283. }
  284. /**
  285. * Checks if this is the last scale on the site.
  286. *
  287. * @return bool
  288. */
  289. public function is_last_global_scale() {
  290. return ($this->courseid == 0) && (count(self::fetch_all_global()) == 1);
  291. }
  292. /**
  293. * Checks if scale can be deleted.
  294. *
  295. * @return bool
  296. */
  297. public function can_delete() {
  298. return !$this->is_used() && !$this->is_last_global_scale();
  299. }
  300. /**
  301. * Returns if scale used anywhere - activities, grade items, outcomes, etc.
  302. *
  303. * @return bool
  304. */
  305. public function is_used() {
  306. global $DB;
  307. global $CFG;
  308. // count grade items excluding the
  309. $params = array($this->id);
  310. $sql = "SELECT COUNT(id) FROM {grade_items} WHERE scaleid = ? AND outcomeid IS NULL";
  311. if ($DB->count_records_sql($sql, $params)) {
  312. return true;
  313. }
  314. // count outcomes
  315. $sql = "SELECT COUNT(id) FROM {grade_outcomes} WHERE scaleid = ?";
  316. if ($DB->count_records_sql($sql, $params)) {
  317. return true;
  318. }
  319. // Ask the competency subsystem.
  320. if (\core_competency\api::is_scale_used_anywhere($this->id)) {
  321. return true;
  322. }
  323. // Ask all plugins if the scale is used anywhere.
  324. $pluginsfunction = get_plugins_with_function('scale_used_anywhere');
  325. foreach ($pluginsfunction as $plugintype => $plugins) {
  326. foreach ($plugins as $pluginfunction) {
  327. if ($pluginfunction($this->id)) {
  328. return true;
  329. }
  330. }
  331. }
  332. return false;
  333. }
  334. /**
  335. * Returns the formatted grade description with URLs converted
  336. *
  337. * @return string
  338. */
  339. public function get_description() {
  340. global $CFG;
  341. require_once($CFG->libdir . '/filelib.php');
  342. $systemcontext = context_system::instance();
  343. $options = new stdClass;
  344. $options->noclean = true;
  345. $description = file_rewrite_pluginfile_urls($this->description, 'pluginfile.php', $systemcontext->id, 'grade', 'scale', $this->id);
  346. return format_text($description, $this->descriptionformat, $options);
  347. }
  348. }