Differences Between: [Versions 310 and 403] [Versions 39 and 403]
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 /** 18 * Class for loading/storing competencies from the DB. 19 * 20 * @package core_competency 21 * @copyright 2015 Damyon Wiese 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace core_competency; 25 26 use coding_exception; 27 use lang_string; 28 use core_course\external\course_summary_exporter; 29 30 /** 31 * Class for loading/storing course_competencies from the DB. 32 * 33 * @copyright 2015 Damyon Wiese 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class course_competency extends persistent { 37 38 const TABLE = 'competency_coursecomp'; 39 40 /** Course competency ruleoutcome constant. */ 41 const OUTCOME_NONE = 0; 42 /** Course competency ruleoutcome constant. */ 43 const OUTCOME_EVIDENCE = 1; 44 /** Course competency ruleoutcome constant. */ 45 const OUTCOME_RECOMMEND = 2; 46 /** Course competency ruleoutcome constant. */ 47 const OUTCOME_COMPLETE = 3; 48 49 /** 50 * Return the definition of the properties of this model. 51 * 52 * @return array 53 */ 54 protected static function define_properties() { 55 return array( 56 'courseid' => array( 57 'type' => PARAM_INT 58 ), 59 'competencyid' => array( 60 'type' => PARAM_INT 61 ), 62 'sortorder' => array( 63 'type' => PARAM_INT 64 ), 65 'ruleoutcome' => array( 66 'choices' => array(self::OUTCOME_NONE, 67 self::OUTCOME_EVIDENCE, 68 self::OUTCOME_RECOMMEND, 69 self::OUTCOME_COMPLETE 70 ), 71 'default' => self::OUTCOME_EVIDENCE, 72 'type' => PARAM_INT, 73 ), 74 ); 75 } 76 77 /** 78 * Hook to execute before validate. 79 * 80 * @return void 81 */ 82 protected function before_validate() { 83 if (($this->get('id') && $this->get('sortorder') === null) || !$this->get('id')) { 84 $this->set('sortorder', $this->count_records(array('courseid' => $this->get('courseid')))); 85 } 86 } 87 88 /** 89 * Return the courses where both competency and user are. 90 * 91 * A user is considered being in a course when they are enrolled, the enrolment is valid, 92 * the enrolment instance is enabled, and the enrolment plugin is enabled.. 93 * 94 * @param int $competencyid The competency ID. 95 * @param int $userid The user ID. 96 * @return array Indexed by course ID. 97 */ 98 public static function get_courses_with_competency_and_user($competencyid, $userid) { 99 global $CFG, $DB; 100 101 if (!$plugins = explode(',', $CFG->enrol_plugins_enabled)) { 102 return array(); 103 } 104 105 $ctxfields = \context_helper::get_preload_record_columns_sql('ctx'); 106 list($plugins, $params) = $DB->get_in_or_equal($plugins, SQL_PARAMS_NAMED, 'ee'); 107 $params['competencyid'] = $competencyid; 108 $params['userid'] = $userid; 109 $params['enabled'] = ENROL_INSTANCE_ENABLED; 110 $params['active'] = ENROL_USER_ACTIVE; 111 $params['contextlevel'] = CONTEXT_COURSE; 112 113 // Heavily based on enrol_get_shared_courses(). 114 $sql = "SELECT c.*, $ctxfields 115 FROM {course} c 116 JOIN {" . static::TABLE . "} cc 117 ON cc.courseid = c.id 118 AND cc.competencyid = :competencyid 119 JOIN ( 120 SELECT DISTINCT c.id 121 FROM {enrol} e 122 JOIN {user_enrolments} ue 123 ON ue.enrolid = e.id 124 AND ue.status = :active 125 AND ue.userid = :userid 126 JOIN {course} c 127 ON c.id = e.courseid 128 WHERE e.status = :enabled 129 AND e.enrol $plugins 130 ) ec ON ec.id = c.id 131 LEFT JOIN {context} ctx 132 ON ctx.instanceid = c.id 133 AND ctx.contextlevel = :contextlevel 134 ORDER BY c.id"; 135 136 $courses = $DB->get_records_sql($sql, $params); 137 array_map('context_helper::preload_from_record', $courses); 138 return $courses; 139 } 140 141 /** 142 * Return a list of rules. 143 * 144 * @return array Indexed by outcome value. 145 */ 146 public static function get_ruleoutcome_list() { 147 static $list = null; 148 149 if ($list === null) { 150 $list = array( 151 self::OUTCOME_NONE => self::get_ruleoutcome_name(self::OUTCOME_NONE), 152 self::OUTCOME_EVIDENCE => self::get_ruleoutcome_name(self::OUTCOME_EVIDENCE), 153 self::OUTCOME_RECOMMEND => self::get_ruleoutcome_name(self::OUTCOME_RECOMMEND), 154 self::OUTCOME_COMPLETE => self::get_ruleoutcome_name(self::OUTCOME_COMPLETE)); 155 } 156 157 return $list; 158 } 159 160 /** 161 * Human readable rule name. 162 * 163 * @param int $ruleoutcome The value of ruleoutcome. 164 * @return lang_string 165 */ 166 public static function get_ruleoutcome_name($ruleoutcome) { 167 168 switch ($ruleoutcome) { 169 case self::OUTCOME_NONE: 170 $strname = 'none'; 171 break; 172 case self::OUTCOME_EVIDENCE: 173 $strname = 'evidence'; 174 break; 175 case self::OUTCOME_RECOMMEND: 176 $strname = 'recommend'; 177 break; 178 case self::OUTCOME_COMPLETE: 179 $strname = 'complete'; 180 break; 181 default: 182 throw new \moodle_exception('errorcoursecompetencyrule', 'core_competency', '', $ruleoutcome); 183 break; 184 } 185 186 return new lang_string('coursecompetencyoutcome_' . $strname, 'core_competency'); 187 } 188 189 /** 190 * Validate course ID. 191 * 192 * @param int $data The course ID. 193 * @return true|lang_string 194 */ 195 protected function validate_courseid($data) { 196 global $DB; 197 if (!$DB->record_exists('course', array('id' => $data))) { 198 return new lang_string('invalidcourseid', 'error'); 199 } 200 return true; 201 } 202 203 /** 204 * Validate competency ID. 205 * 206 * @param int $data The competency ID. 207 * @return true|lang_string 208 */ 209 protected function validate_competencyid($data) { 210 if (!competency::record_exists($data)) { 211 return new lang_string('invaliddata', 'error'); 212 } 213 return true; 214 } 215 216 /** 217 * Return the course IDs and visible flags that include this competency. 218 * 219 * Only the ids and visible flag are returned, for the full records use list_courses. 220 * 221 * @param int $competencyid The competency id 222 * @return array containing courseid and visible. 223 */ 224 public static function list_courses_min($competencyid) { 225 global $DB; 226 227 $results = $DB->get_records_sql('SELECT course.id as id, course.visible as visible 228 FROM {' . self::TABLE . '} coursecomp 229 JOIN {course} course 230 ON coursecomp.courseid = course.id 231 WHERE coursecomp.competencyid = ? ', array($competencyid)); 232 233 return $results; 234 } 235 236 /** 237 * Return partial course records foreach course that contains this competency. 238 * 239 * @param int $competencyid The competency id 240 * @return array[stdClass] Array of course records containg id, visible, shortname, idnumber, fullname 241 */ 242 public static function list_courses($competencyid) { 243 global $DB; 244 245 // We need all the course summary exporter properties, plus category. 246 $coursefields = course_summary_exporter::properties_definition(); 247 $coursefields = array_map(function(string $field): string { 248 return "course.{$field}"; 249 }, array_keys($coursefields)); 250 251 $results = $DB->get_records_sql('SELECT ' . implode(',', $coursefields) . ', course.category 252 FROM {course} course 253 JOIN {' . self::TABLE . '} coursecomp 254 ON coursecomp.courseid = course.id 255 WHERE coursecomp.competencyid = ? ', array($competencyid)); 256 257 return $results; 258 } 259 260 /** 261 * Count the competencies in this course. 262 * 263 * @param int $courseid The course id 264 * @return int 265 */ 266 public static function count_competencies($courseid) { 267 global $DB; 268 269 $sql = 'SELECT COUNT(comp.id) 270 FROM {' . self::TABLE . '} coursecomp 271 JOIN {' . competency::TABLE . '} comp 272 ON coursecomp.competencyid = comp.id 273 WHERE coursecomp.courseid = ? '; 274 $params = array($courseid); 275 276 $results = $DB->count_records_sql($sql, $params); 277 278 return $results; 279 } 280 281 /** 282 * List the competencies in this course. 283 * 284 * @param int $courseid The course id 285 * @return competency[] Indexed by competency ID. 286 */ 287 public static function list_competencies($courseid) { 288 global $DB; 289 290 $sql = 'SELECT comp.* 291 FROM {' . competency::TABLE . '} comp 292 JOIN {' . self::TABLE . '} coursecomp 293 ON coursecomp.competencyid = comp.id 294 WHERE coursecomp.courseid = ?'; 295 $params = array($courseid); 296 297 $sql .= ' ORDER BY coursecomp.sortorder ASC'; 298 $results = $DB->get_recordset_sql($sql, $params); 299 $instances = array(); 300 foreach ($results as $result) { 301 $comp = new competency(0, $result); 302 $instances[$comp->get('id')] = $comp; 303 } 304 $results->close(); 305 306 return $instances; 307 } 308 309 /** 310 * Get a single competency from the course (only if it is really in the course). 311 * 312 * @param int $courseid The course id 313 * @param int $competencyid The competency id 314 * @return competency 315 */ 316 public static function get_competency($courseid, $competencyid) { 317 global $DB; 318 319 $sql = 'SELECT comp.* 320 FROM {' . competency::TABLE . '} comp 321 JOIN {' . self::TABLE . '} crscomp 322 ON crscomp.competencyid = comp.id 323 WHERE crscomp.courseid = ? AND crscomp.competencyid = ?'; 324 $params = array($courseid, $competencyid); 325 326 $result = $DB->get_record_sql($sql, $params); 327 if (!$result) { 328 throw new coding_exception('The competency does not belong to this course: ' . $competencyid . ', ' . $courseid); 329 } 330 331 return new competency(0, $result); 332 } 333 334 /** 335 * Hook to execute after delete. 336 * 337 * @param bool $result Whether or not the delete was successful. 338 * @return void 339 */ 340 protected function after_delete($result) { 341 global $DB; 342 if (!$result) { 343 return; 344 } 345 346 $table = '{' . self::TABLE . '}'; 347 $sql = "UPDATE $table SET sortorder = sortorder -1 WHERE courseid = ? AND sortorder > ?"; 348 $DB->execute($sql, array($this->get('courseid'), $this->get('sortorder'))); 349 } 350 351 /** 352 * Get the specified course_competency in this course. 353 * 354 * @param int $courseid The course id 355 * @param int $competencyid The competency id 356 * @return course_competency 357 */ 358 public static function get_course_competency($courseid, $competencyid) { 359 global $DB; 360 361 $sql = 'SELECT crscomp.* 362 FROM {' . self::TABLE . '} crscomp 363 WHERE crscomp.courseid = ? AND crscomp.competencyid = ?'; 364 $params = array($courseid, $competencyid); 365 366 $result = $DB->get_record_sql($sql, $params); 367 if (!$result) { 368 throw new coding_exception('The competency does not belong to this course: ' . $competencyid . ', ' . $courseid); 369 } 370 371 return new course_competency(0, $result); 372 } 373 374 /** 375 * List the course_competencies in this course. 376 * 377 * @param int $courseid The course id 378 * @return course_competency[] 379 */ 380 public static function list_course_competencies($courseid) { 381 global $DB; 382 383 $sql = 'SELECT coursecomp.* 384 FROM {' . self::TABLE . '} coursecomp 385 JOIN {' . competency::TABLE . '} comp 386 ON coursecomp.competencyid = comp.id 387 WHERE coursecomp.courseid = ?'; 388 $params = array($courseid); 389 390 $sql .= ' ORDER BY coursecomp.sortorder ASC'; 391 $results = $DB->get_recordset_sql($sql, $params); 392 $instances = array(); 393 foreach ($results as $result) { 394 array_push($instances, new course_competency(0, $result)); 395 } 396 $results->close(); 397 398 return $instances; 399 } 400 401 /** 402 * Check if course competency has records for competencies. 403 * 404 * @param array $competencyids Array of competencies ids. 405 * @return boolean Return true if one or more than a competency was found in a course. 406 */ 407 public static function has_records_for_competencies($competencyids) { 408 global $DB; 409 list($insql, $params) = $DB->get_in_or_equal($competencyids, SQL_PARAMS_NAMED); 410 return self::record_exists_select("competencyid $insql", $params); 411 } 412 413 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body