Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   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   * This file contains the cohort membership badge award criteria type class
  19   *
  20   * @package    core
  21   * @subpackage badges
  22   * @copyright  2016 onwards Catalyst IT {@link https://www.catalyst.net.nz/}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @author     Eugene Venter <eugene@catalyst.net.nz>
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  require_once($CFG->dirroot.'/cohort/lib.php');
  30  
  31  /**
  32   * Badge award criteria -- award on cohort membership
  33   *
  34   * @package    core
  35   * @subpackage badges
  36   * @copyright  2016 onwards Catalyst IT {@link https://www.catalyst.net.nz/}
  37   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   * @author     Eugene Venter <eugene@catalyst.net.nz>
  39   */
  40  class award_criteria_cohort extends award_criteria {
  41  
  42      /* @var int $criteriatype Criteria [BADGE_CRITERIA_TYPE_COHORT] */
  43      public $criteriatype = BADGE_CRITERIA_TYPE_COHORT;
  44  
  45      /* @var string $required_param Required form param */
  46      public $required_param = 'cohort';
  47  
  48      /* @var array $optional_params Optional form params */
  49      public $optional_params = array();
  50  
  51      /**
  52       * Get criteria details for displaying to users
  53       * @param string $short Print short version of criteria
  54       * @return string
  55       */
  56      public function get_details($short = '') {
  57          global $DB, $OUTPUT;
  58          $output = array();
  59          foreach ($this->params as $p) {
  60              $cohortname = $DB->get_field('cohort', 'name', array('id' => $p['cohort']));
  61              if (!$cohortname) {
  62                  $str = $OUTPUT->error_text(get_string('error:nosuchcohort', 'badges'));
  63              } else {
  64                  $str = html_writer::tag('b', '"' . format_string($cohortname, true) . '"');
  65              }
  66              $output[] = $str;
  67          }
  68  
  69          if ($short) {
  70              return implode(', ', $output);
  71          } else {
  72              return html_writer::alist($output, array(), 'ul');
  73          }
  74      }
  75  
  76  
  77      /**
  78       * Add appropriate new criteria options to the form
  79       *
  80       * @param object $mform moodle form
  81       */
  82      public function get_options(&$mform) {
  83          global $DB;
  84          $none = false;
  85  
  86          $mform->addElement('header', 'first_header', $this->get_title());
  87          $mform->addHelpButton('first_header', 'criteria_' . $this->criteriatype, 'badges');
  88  
  89          // Get cohorts.
  90          $cohorts = $DB->get_records_menu('cohort', array(), 'name ASC', 'id, name');
  91          if (!empty($cohorts)) {
  92              $select = array();
  93              $selected = array();
  94              foreach ($cohorts as $cid => $cohortname) {
  95                  $select[$cid] = format_string($cohortname, true);
  96              }
  97  
  98              if ($this->id !== 0) {
  99                  $selected = array_keys($this->params);
 100              }
 101              $settings = array('multiple' => 'multiple', 'size' => 20, 'class' => 'selectcohort');
 102              $mform->addElement('select', 'cohort_cohorts', get_string('addcohort', 'badges'), $select, $settings);
 103              $mform->addRule('cohort_cohorts', get_string('requiredcohort', 'badges'), 'required');
 104              $mform->addHelpButton('cohort_cohorts', 'addcohort', 'badges');
 105  
 106              if ($this->id !== 0) {
 107                  $mform->setDefault('cohort_cohorts', $selected);
 108              }
 109          } else {
 110              $mform->addElement('static', 'nocohorts', '', get_string('error:nocohorts', 'badges'));
 111              $none = true;
 112          }
 113  
 114          // Add aggregation.
 115          if (!$none) {
 116              $mform->addElement('header', 'aggregation', get_string('method', 'badges'));
 117              $agg = array();
 118              $agg[] =& $mform->createElement('radio', 'agg', '', get_string('allmethodcohort', 'badges'), 1);
 119              $agg[] =& $mform->createElement('radio', 'agg', '', get_string('anymethodcohort', 'badges'), 2);
 120              $mform->addGroup($agg, 'methodgr', '', array('<br/>'), false);
 121              if ($this->id !== 0) {
 122                  $mform->setDefault('agg', $this->method);
 123              } else {
 124                  $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY);
 125              }
 126          }
 127  
 128          return array($none, get_string('noparamstoadd', 'badges'));
 129      }
 130  
 131      /**
 132       * Save criteria records
 133       *
 134       * @param array $params Values from the form or any other array.
 135       */
 136      public function save($params = array()) {
 137          $cohorts = $params['cohort_cohorts'];
 138  
 139          unset($params['cohort_cohorts']);
 140          foreach ($cohorts as $cohortid) {
 141              $params["cohort_{$cohortid}"] = $cohortid;
 142          }
 143  
 144          parent::save($params);
 145      }
 146  
 147      /**
 148       * Review this criteria and decide if it has been completed
 149       *
 150       * @param int $userid User whose criteria completion needs to be reviewed.
 151       * @param bool $filtered An additional parameter indicating that user list
 152       *        has been reduced and some expensive checks can be skipped.
 153       *
 154       * @return bool Whether criteria is complete.
 155       */
 156      public function review($userid, $filtered = false) {
 157          global $DB;
 158          $overall = false;
 159  
 160          foreach ($this->params as $param) {
 161              $cohort = $DB->get_record('cohort', array('id' => $param['cohort']));
 162  
 163              // Extra check in case a cohort was deleted while badge is still active.
 164              if (!$cohort) {
 165                  if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) {
 166                      return false;
 167                  } else {
 168                      continue;
 169                  }
 170              }
 171  
 172              if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) {
 173                  if (cohort_is_member($cohort->id, $userid)) {
 174                      $overall = true;
 175                      continue;
 176                  } else {
 177                      return false;
 178                  }
 179              } else if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) {
 180                  if (cohort_is_member($cohort->id, $userid)) {
 181                      return true;
 182                  } else {
 183                      $overall = false;
 184                      continue;
 185                  }
 186              }
 187          }
 188  
 189          return $overall;
 190      }
 191  
 192      /**
 193       * Checks criteria for any major problems.
 194       *
 195       * @return array A list containing status and an error message (if any).
 196       */
 197      public function validate() {
 198          global $DB;
 199          $params = array_keys($this->params);
 200          $method = ($this->method == BADGE_CRITERIA_AGGREGATION_ALL);
 201          $singleparam = (count($params) == 1);
 202  
 203          foreach ($params as $param) {
 204              // Perform check if there only one parameter with any type of aggregation,
 205              // Or there are more than one parameter with aggregation ALL.
 206              if (($singleparam || $method) && !$DB->record_exists('cohort', array('id' => $param))) {
 207                  return array(false, get_string('error:invalidparamcohort', 'badges'));
 208              }
 209          }
 210  
 211          return array(true, '');
 212      }
 213  
 214      /**
 215       * Returns array with sql code and parameters returning all ids
 216       * of users who meet this particular criterion.
 217       *
 218       * @return array list($join, $where, $params)
 219       */
 220      public function get_completed_criteria_sql() {
 221          $join = '';
 222          $where = '';
 223          $params = array();
 224  
 225          if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) {
 226              // User is a member of ANY of the specified cohorts.
 227              $join = " LEFT JOIN {cohort_members} cm ON cm.userid = u.id";
 228              $where = "AND (";
 229              $i = 0;
 230              foreach ($this->params as $param) {
 231                  if ($i == 0) {
 232                      $where .= ' cm.cohortid = :cohortid'.$i;
 233                  } else {
 234                      $where .= ' OR cm.cohortid = :cohortid'.$i;
 235                  }
 236                  $params['cohortid'.$i] = $param['cohort'];
 237                  $i++;
 238              }
 239              $where .= ") ";
 240              return array($join, $where, $params);
 241          } else {
 242              // User is a member of ALL of the specified cohorts.
 243              $join = ' LEFT JOIN {cohort_members} cm ON cm.userid = u.id';
 244              $where = ' AND (';
 245              $i = 0;
 246              foreach ($this->params as $param) {
 247                  if ($i == 0) {
 248                      $where .= 'cm.cohortid = :cohortid'.$i;
 249                  } else {
 250                      $where .= ' OR cm.cohortid = :cohortid'.$i;
 251                  }
 252                  $params['cohortid'.$i] = $param['cohort'];
 253                  $i++;
 254              }
 255              $where .= ')
 256                  GROUP BY u.id, bi.badgeid
 257                  HAVING COUNT(cm.cohortid) = :cohortcount';
 258              $params['cohortcount'] = $i;
 259  
 260              return array($join, $where, $params);
 261          }
 262      }
 263  }