Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

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