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 badge earned badge award criteria type class 19 * 20 * @package core 21 * @subpackage badges 22 * @copyright 2017 Stephen Bourget 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Badge award criteria -- award on badge completion 30 * 31 * @package core 32 * @subpackage badges 33 * @copyright 2017 Stephen Bourget 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class award_criteria_badge extends award_criteria { 37 38 /* @var int Criteria [BADGE_CRITERIA_TYPE_BADGE] */ 39 public $criteriatype = BADGE_CRITERIA_TYPE_BADGE; 40 41 public $required_param = 'badge'; 42 public $optional_params = array(); 43 44 /** 45 * Get criteria details for displaying to users 46 * @param string $short Print short version of criteria 47 * @return string 48 */ 49 public function get_details($short = '') { 50 global $DB, $OUTPUT; 51 $output = array(); 52 foreach ($this->params as $p) { 53 $badgename = $DB->get_field('badge', 'name', array('id' => $p['badge'])); 54 if (!$badgename) { 55 $str = $OUTPUT->error_text(get_string('error:nosuchbadge', 'badges')); 56 } else { 57 $str = html_writer::tag('b', '"' . $badgename . '"'); 58 } 59 $output[] = $str; 60 } 61 62 if ($short) { 63 return implode(', ', $output); 64 } else { 65 return html_writer::alist($output, array(), 'ul'); 66 } 67 } 68 69 /** 70 * Add appropriate new criteria options to the form 71 * @param object $mform moodle form 72 */ 73 public function get_options(&$mform) { 74 global $DB; 75 $none = false; 76 $availablebadges = null; 77 78 $mform->addElement('header', 'first_header', $this->get_title()); 79 $mform->addHelpButton('first_header', 'criteria_' . $this->criteriatype, 'badges'); 80 81 // Determine if this badge is a course badge or a site badge. 82 $thisbadge = $DB->get_record('badge', array('id' => $this->badgeid)); 83 84 if ($thisbadge->type == BADGE_TYPE_SITE) { 85 // Only list site badges that are enabled. 86 $select = " type = :site AND (status = :status1 OR status = :status2)"; 87 $params = array('site' => BADGE_TYPE_SITE, 88 'status1' => BADGE_STATUS_ACTIVE, 89 'status2' => BADGE_STATUS_ACTIVE_LOCKED); 90 $availablebadges = $DB->get_records_select_menu('badge', $select, $params, 'name ASC', 'id, name'); 91 92 } else if ($thisbadge->type == BADGE_TYPE_COURSE) { 93 // List both site badges and course badges belonging to this course. 94 $select = " (type = :site OR (type = :course AND courseid = :courseid)) AND (status = :status1 OR status = :status2)"; 95 $params = array('site' => BADGE_TYPE_SITE, 96 'course' => BADGE_TYPE_COURSE, 97 'courseid' => $thisbadge->courseid, 98 'status1' => BADGE_STATUS_ACTIVE, 99 'status2' => BADGE_STATUS_ACTIVE_LOCKED); 100 $availablebadges = $DB->get_records_select_menu('badge', $select, $params, 'name ASC', 'id, name'); 101 } 102 if (!empty($availablebadges)) { 103 $select = array(); 104 $selected = array(); 105 foreach ($availablebadges as $bid => $badgename) { 106 if ($bid != $this->badgeid) { 107 // Do not let it use itself as criteria. 108 $select[$bid] = format_string($badgename, true); 109 } 110 } 111 112 if ($this->id !== 0) { 113 $selected = array_keys($this->params); 114 } 115 $settings = array('multiple' => 'multiple', 'size' => 20, 'class' => 'selectbadge', 'required' => 'required'); 116 $mform->addElement('select', 'badge_badges', get_string('addbadge', 'badges'), $select, $settings); 117 $mform->addRule('badge_badges', get_string('requiredbadge', 'badges'), 'required'); 118 $mform->addHelpButton('badge_badges', 'addbadge', 'badges'); 119 120 if ($this->id !== 0) { 121 $mform->setDefault('badge_badges', $selected); 122 } 123 } else { 124 $mform->addElement('static', 'nobadges', '', get_string('error:nobadges', 'badges')); 125 $none = true; 126 } 127 128 // Add aggregation. 129 if (!$none) { 130 $mform->addElement('header', 'aggregation', get_string('method', 'badges')); 131 $agg = array(); 132 $agg[] =& $mform->createElement('radio', 'agg', '', get_string('allmethodbadges', 'badges'), 1); 133 $agg[] =& $mform->createElement('radio', 'agg', '', get_string('anymethodbadges', 'badges'), 2); 134 $mform->addGroup($agg, 'methodgr', '', array('<br/>'), false); 135 if ($this->id !== 0) { 136 $mform->setDefault('agg', $this->method); 137 } else { 138 $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY); 139 } 140 } 141 142 return array($none, get_string('noparamstoadd', 'badges')); 143 } 144 145 /** 146 * Save criteria records 147 * 148 * @param array $params Values from the form or any other array. 149 */ 150 public function save($params = array()) { 151 $badges = $params['badge_badges']; 152 unset($params['badge_badges']); 153 foreach ($badges as $badgeid) { 154 $params["badge_{$badgeid}"] = $badgeid; 155 } 156 157 parent::save($params); 158 } 159 160 /** 161 * Review this criteria and decide if it has been completed 162 * 163 * @param int $userid User whose criteria completion needs to be reviewed. 164 * @param bool $filtered An additional parameter indicating that user list 165 * has been reduced and some expensive checks can be skipped. 166 * 167 * @return bool Whether criteria is complete. 168 */ 169 public function review($userid, $filtered = false) { 170 171 global $DB; 172 $overall = false; 173 174 foreach ($this->params as $param) { 175 $badge = $DB->get_record('badge', array('id' => $param['badge'])); 176 // See if the user has earned this badge. 177 $awarded = $DB->get_record('badge_issued', array('badgeid' => $param['badge'], 'userid' => $userid)); 178 179 // Extra check in case a badge was deleted while this badge is still active. 180 if (!$badge) { 181 if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) { 182 return false; 183 } else { 184 continue; 185 } 186 } 187 188 if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) { 189 190 if ($awarded) { 191 $overall = true; 192 continue; 193 } else { 194 return false; 195 } 196 } else if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) { 197 if ($awarded) { 198 return true; 199 } else { 200 $overall = false; 201 continue; 202 } 203 } 204 } 205 206 return $overall; 207 } 208 209 /** 210 * Checks criteria for any major problems. 211 * 212 * @return array A list containing status and an error message (if any). 213 */ 214 public function validate() { 215 global $DB; 216 $params = array_keys($this->params); 217 $method = ($this->method == BADGE_CRITERIA_AGGREGATION_ALL); 218 $singleparam = (count($params) == 1); 219 220 foreach ($params as $param) { 221 // Perform check if there only one parameter with any type of aggregation, 222 // Or there are more than one parameter with aggregation ALL. 223 224 if (($singleparam || $method) && !$DB->record_exists('badge', array('id' => $param))) { 225 return array(false, get_string('error:invalidparambadge', 'badges')); 226 } 227 } 228 229 return array(true, ''); 230 } 231 232 /** 233 * Returns array with sql code and parameters returning all ids 234 * of users who meet this particular criterion. 235 * 236 * @return array list($join, $where, $params) 237 */ 238 public function get_completed_criteria_sql() { 239 $join = ''; 240 $where = ''; 241 $params = array(); 242 243 if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) { 244 // User has received ANY of the required badges. 245 $join = " LEFT JOIN {badge_issued} bi2 ON bi2.userid = u.id"; 246 $i = 0; 247 foreach ($this->params as $param) { 248 if ($i == 0) { 249 $where .= ' bi2.badgeid = :badgeid'.$i; 250 } else { 251 $where .= ' OR bi2.badgeid = :badgeid'.$i; 252 } 253 $params['badgeid'.$i] = $param['badge']; 254 $i++; 255 } 256 // MDL-66032 Do not create expression if there are no badges in criteria. 257 if (!empty($where)) { 258 $where = ' AND (' . $where . ') '; 259 } 260 return array($join, $where, $params); 261 } else { 262 // User has received ALL of the required badges. 263 $join = " LEFT JOIN {badge_issued} bi2 ON bi2.userid = u.id"; 264 $i = 0; 265 foreach ($this->params as $param) { 266 $i++; 267 $where = ' AND bi2.badgeid = :badgeid'.$i; 268 $params['badgeid'.$i] = $param['badge']; 269 } 270 return array($join, $where, $params); 271 } 272 } 273 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body