Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 39 and 311]

   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 manual badge award criteria type class
  19   *
  20   * @package    core
  21   * @subpackage badges
  22   * @copyright  2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @author     Yuliya Bozhko <yuliya.bozhko@totaralms.com>
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Manual badge award criteria
  31   *
  32   */
  33  class award_criteria_manual extends award_criteria {
  34  
  35      /* @var int Criteria [BADGE_CRITERIA_TYPE_MANUAL] */
  36      public $criteriatype = BADGE_CRITERIA_TYPE_MANUAL;
  37  
  38      public $required_param = 'role';
  39      public $optional_params = array();
  40  
  41      /**
  42       * Gets role name.
  43       * If no such role exists this function returns null.
  44       *
  45       * @return string|null
  46       */
  47      private function get_role_name($rid) {
  48          global $DB, $PAGE;
  49          $rec = $DB->get_record('role', array('id' => $rid));
  50  
  51          if ($rec) {
  52              return role_get_name($rec, $PAGE->context, ROLENAME_BOTH);
  53          } else {
  54              return null;
  55          }
  56      }
  57  
  58      /**
  59       * Add appropriate new criteria options to the form
  60       *
  61       */
  62      public function get_options(&$mform) {
  63          global $PAGE;
  64          $options = '';
  65          $none = true;
  66  
  67          $roles = get_roles_with_capability('moodle/badges:awardbadge', CAP_ALLOW, $PAGE->context);
  68          $visibleroles = get_viewable_roles($PAGE->context);
  69          $roleids = array_map(function($o) {
  70              return $o->id;
  71          }, $roles);
  72          $existing = array();
  73          $missing = array();
  74  
  75          if ($this->id !== 0) {
  76              $existing = array_keys($this->params);
  77              $missing = array_diff($existing, $roleids);
  78          }
  79  
  80          if (!empty($missing)) {
  81              $mform->addElement('header', 'category_errors', get_string('criterror', 'badges'));
  82              $mform->addHelpButton('category_errors', 'criterror', 'badges');
  83              foreach ($missing as $m) {
  84                  $this->config_options($mform, array('id' => $m, 'checked' => true, 'name' => get_string('error:nosuchrole', 'badges'), 'error' => true));
  85                  $none = false;
  86              }
  87          }
  88  
  89          if (!empty($roleids)) {
  90              $mform->addElement('header', 'first_header', $this->get_title());
  91              $mform->addHelpButton('first_header', 'criteria_' . $this->criteriatype, 'badges');
  92              foreach ($roleids as $rid) {
  93                  if (!key_exists($rid, $visibleroles)) {
  94                      continue;
  95                  }
  96                  $checked = false;
  97                  if (in_array($rid, $existing)) {
  98                      $checked = true;
  99                  }
 100                  $this->config_options($mform, array('id' => $rid, 'checked' => $checked, 'name' => self::get_role_name($rid), 'error' => false));
 101                  $none = false;
 102              }
 103          }
 104  
 105          // Add aggregation.
 106          if (!$none) {
 107              $mform->addElement('header', 'aggregation', get_string('method', 'badges'));
 108              $agg = array();
 109              $agg[] =& $mform->createElement('radio', 'agg', '', get_string('allmethodmanual', 'badges'), 1);
 110              $agg[] =& $mform->createElement('static', 'none_break', null, '<br/>');
 111              $agg[] =& $mform->createElement('radio', 'agg', '', get_string('anymethodmanual', 'badges'), 2);
 112              $mform->addGroup($agg, 'methodgr', '', array(' '), false);
 113              if ($this->id !== 0) {
 114                  $mform->setDefault('agg', $this->method);
 115              } else {
 116                  $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY);
 117              }
 118          }
 119  
 120          return array($none, get_string('noparamstoadd', 'badges'));
 121      }
 122  
 123      /**
 124       * Get criteria details for displaying to users
 125       *
 126       * @return string
 127       */
 128      public function get_details($short = '') {
 129          global $OUTPUT;
 130          $output = array();
 131          foreach ($this->params as $p) {
 132              $str = self::get_role_name($p['role']);
 133              if (!$str) {
 134                  $output[] = $OUTPUT->error_text(get_string('error:nosuchrole', 'badges'));
 135              } else {
 136                  $output[] = $str;
 137              }
 138          }
 139  
 140          if ($short) {
 141              return implode(', ', $output);
 142          } else {
 143              return html_writer::alist($output, array(), 'ul');
 144          }
 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  
 159          // Roles should always have a parameter.
 160          if (empty($this->params)) {
 161              return false;
 162          }
 163  
 164          // Users were already filtered by criteria completion.
 165          if ($filtered) {
 166              return true;
 167          }
 168  
 169          $overall = false;
 170          foreach ($this->params as $param) {
 171              $crit = $DB->get_record('badge_manual_award', array('issuerrole' => $param['role'], 'recipientid' => $userid, 'badgeid' => $this->badgeid));
 172              if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) {
 173                  if (!$crit) {
 174                      return false;
 175                  } else {
 176                      $overall = true;
 177                      continue;
 178                  }
 179              } else {
 180                  if (!$crit) {
 181                      $overall = false;
 182                      continue;
 183                  } else {
 184                      return true;
 185                  }
 186              }
 187          }
 188          return $overall;
 189      }
 190  
 191      /**
 192       * Returns array with sql code and parameters returning all ids
 193       * of users who meet this particular criterion.
 194       *
 195       * @return array list($join, $where, $params)
 196       */
 197      public function get_completed_criteria_sql() {
 198          $join = '';
 199          $where = '';
 200          $params = array();
 201  
 202          if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) {
 203              foreach ($this->params as $param) {
 204                  $roledata[] = " bma.issuerrole = :issuerrole{$param['role']} ";
 205                  $params["issuerrole{$param['role']}"] = $param['role'];
 206              }
 207              if (!empty($roledata)) {
 208                  $extraon = implode(' OR ', $roledata);
 209                  $join = " JOIN {badge_manual_award} bma ON bma.recipientid = u.id
 210                            AND bma.badgeid = :badgeid{$this->badgeid} AND ({$extraon})";
 211                  $params["badgeid{$this->badgeid}"] = $this->badgeid;
 212              }
 213              return array($join, $where, $params);
 214          } else {
 215              foreach ($this->params as $param) {
 216                  $roledata[] = " bma.issuerrole = :issuerrole{$param['role']} ";
 217                  $params["issuerrole{$param['role']}"] = $param['role'];
 218              }
 219              if (!empty($roledata)) {
 220                  $extraon = implode(' AND ', $roledata);
 221                  $join = " JOIN {badge_manual_award} bma ON bma.recipientid = u.id
 222                            AND bma.badgeid = :badgeid{$this->badgeid} AND ({$extraon})";
 223                  $params["badgeid{$this->badgeid}"] = $this->badgeid;
 224              }
 225              return array($join, $where, $params);
 226          }
 227      }
 228  
 229      /**
 230       * Delete this criterion
 231       *
 232       */
 233      public function delete() {
 234          global $DB;
 235  
 236          // Remove any records of manual award.
 237          $DB->delete_records('badge_manual_award', array('badgeid' => $this->badgeid));
 238  
 239          parent::delete();
 240      }
 241  }