Differences Between: [Versions 310 and 311] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [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 activity 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 require_once($CFG->libdir . '/completionlib.php'); 29 30 /** 31 * Badge award criteria -- award on activity completion 32 * 33 */ 34 class award_criteria_activity extends award_criteria { 35 36 /* @var int Criteria [BADGE_CRITERIA_TYPE_ACTIVITY] */ 37 public $criteriatype = BADGE_CRITERIA_TYPE_ACTIVITY; 38 39 private $courseid; 40 private $course; 41 42 public $required_param = 'module'; 43 public $optional_params = array('bydate'); 44 45 public function __construct($record) { 46 global $DB; 47 parent::__construct($record); 48 49 $this->course = $DB->get_record_sql('SELECT c.id, c.enablecompletion, c.cacherev, c.startdate 50 FROM {badge} b LEFT JOIN {course} c ON b.courseid = c.id 51 WHERE b.id = :badgeid ', array('badgeid' => $this->badgeid), MUST_EXIST); 52 53 // If the course doesn't exist but we're sure the badge does (thanks to the LEFT JOIN), then use the site as the course. 54 if (empty($this->course->id)) { 55 $this->course = get_course(SITEID); 56 } 57 $this->courseid = $this->course->id; 58 } 59 60 /** 61 * Gets the module instance from the database and returns it. 62 * If no module instance exists this function returns false. 63 * 64 * @return stdClass|bool 65 */ 66 private function get_mod_instance($cmid) { 67 global $DB; 68 $rec = $DB->get_record_sql("SELECT md.name 69 FROM {course_modules} cm, 70 {modules} md 71 WHERE cm.id = ? AND 72 md.id = cm.module", array($cmid)); 73 74 if ($rec) { 75 return get_coursemodule_from_id($rec->name, $cmid); 76 } else { 77 return null; 78 } 79 } 80 81 /** 82 * Get criteria description for displaying to users 83 * 84 * @return string 85 */ 86 public function get_details($short = '') { 87 global $DB, $OUTPUT; 88 $output = array(); 89 foreach ($this->params as $p) { 90 $mod = self::get_mod_instance($p['module']); 91 if (!$mod) { 92 $str = $OUTPUT->error_text(get_string('error:nosuchmod', 'badges')); 93 } else { 94 $str = html_writer::tag('b', '"' . get_string('modulename', $mod->modname) . ' - ' . $mod->name . '"'); 95 if (isset($p['bydate'])) { 96 $str .= get_string('criteria_descr_bydate', 'badges', userdate($p['bydate'], get_string('strftimedate', 'core_langconfig'))); 97 } 98 } 99 $output[] = $str; 100 } 101 102 if ($short) { 103 return implode(', ', $output); 104 } else { 105 return html_writer::alist($output, array(), 'ul'); 106 } 107 } 108 109 /** 110 * Add appropriate new criteria options to the form 111 * 112 */ 113 public function get_options(&$mform) { 114 $none = true; 115 $existing = array(); 116 $missing = array(); 117 118 $course = $this->course; 119 $info = new completion_info($course); 120 $mods = $info->get_activities(); 121 $mids = array_keys($mods); 122 123 if ($this->id !== 0) { 124 $existing = array_keys($this->params); 125 $missing = array_diff($existing, $mids); 126 } 127 128 if (!empty($missing)) { 129 $mform->addElement('header', 'category_errors', get_string('criterror', 'badges')); 130 $mform->addHelpButton('category_errors', 'criterror', 'badges'); 131 foreach ($missing as $m) { 132 $this->config_options($mform, array('id' => $m, 'checked' => true, 133 'name' => get_string('error:nosuchmod', 'badges'), 'error' => true)); 134 $none = false; 135 } 136 } 137 138 if (!empty($mods)) { 139 $mform->addElement('header', 'first_header', $this->get_title()); 140 foreach ($mods as $mod) { 141 $checked = false; 142 if (in_array($mod->id, $existing)) { 143 $checked = true; 144 } 145 $param = array('id' => $mod->id, 146 'checked' => $checked, 147 'name' => get_string('modulename', $mod->modname) . ' - ' . $mod->name, 148 'error' => false 149 ); 150 151 if ($this->id !== 0 && isset($this->params[$mod->id]['bydate'])) { 152 $param['bydate'] = $this->params[$mod->id]['bydate']; 153 } 154 155 if ($this->id !== 0 && isset($this->params[$mod->id]['grade'])) { 156 $param['grade'] = $this->params[$mod->id]['grade']; 157 } 158 159 $this->config_options($mform, $param); 160 $none = false; 161 } 162 } 163 164 // Add aggregation. 165 if (!$none) { 166 $mform->addElement('header', 'aggregation', get_string('method', 'badges')); 167 $agg = array(); 168 $agg[] =& $mform->createElement('radio', 'agg', '', get_string('allmethodactivity', 'badges'), 1); 169 $agg[] =& $mform->createElement('radio', 'agg', '', get_string('anymethodactivity', 'badges'), 2); 170 $mform->addGroup($agg, 'methodgr', '', array('<br/>'), false); 171 if ($this->id !== 0) { 172 $mform->setDefault('agg', $this->method); 173 } else { 174 $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY); 175 } 176 } 177 178 return array($none, get_string('error:noactivities', 'badges')); 179 } 180 181 /** 182 * Review this criteria and decide if it has been completed 183 * 184 * @param int $userid User whose criteria completion needs to be reviewed. 185 * @param bool $filtered An additional parameter indicating that user list 186 * has been reduced and some expensive checks can be skipped. 187 * 188 * @return bool Whether criteria is complete 189 */ 190 public function review($userid, $filtered = false) { 191 $completionstates = array(COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS, COMPLETION_COMPLETE_FAIL); 192 193 if ($this->course->startdate > time()) { 194 return false; 195 } 196 197 $info = new completion_info($this->course); 198 199 $overall = false; 200 foreach ($this->params as $param) { 201 $cm = new stdClass(); 202 $cm->id = $param['module']; 203 204 $data = $info->get_data($cm, false, $userid); 205 $check_date = true; 206 207 if (isset($param['bydate'])) { 208 $date = $data->timemodified; 209 $check_date = ($date <= $param['bydate']); 210 } 211 212 if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) { 213 if (in_array($data->completionstate, $completionstates) && $check_date) { 214 $overall = true; 215 continue; 216 } else { 217 return false; 218 } 219 } else { 220 if (in_array($data->completionstate, $completionstates) && $check_date) { 221 return true; 222 } else { 223 $overall = false; 224 continue; 225 } 226 } 227 } 228 229 return $overall; 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 foreach ($this->params as $param) { 245 $moduledata[] = " cmc.coursemoduleid = :completedmodule{$param['module']} "; 246 $params["completedmodule{$param['module']}"] = $param['module']; 247 } 248 if (!empty($moduledata)) { 249 $extraon = implode(' OR ', $moduledata); 250 $join = " JOIN {course_modules_completion} cmc ON cmc.userid = u.id AND 251 ( cmc.completionstate = :completionfail OR 252 cmc.completionstate = :completionpass OR 253 cmc.completionstate = :completioncomplete ) AND ({$extraon})"; 254 $params["completionpass"] = COMPLETION_COMPLETE_PASS; 255 $params["completionfail"] = COMPLETION_COMPLETE_FAIL; 256 $params["completioncomplete"] = COMPLETION_COMPLETE; 257 } 258 return array($join, $where, $params); 259 } else { 260 foreach ($this->params as $param) { 261 $join .= " LEFT JOIN {course_modules_completion} cmc{$param['module']} ON 262 cmc{$param['module']}.userid = u.id AND 263 cmc{$param['module']}.coursemoduleid = :completedmodule{$param['module']} AND 264 ( cmc{$param['module']}.completionstate = :completionpass{$param['module']} OR 265 cmc{$param['module']}.completionstate = :completionfail{$param['module']} OR 266 cmc{$param['module']}.completionstate = :completioncomplete{$param['module']} )"; 267 $where .= " AND cmc{$param['module']}.coursemoduleid IS NOT NULL "; 268 $params["completedmodule{$param['module']}"] = $param['module']; 269 $params["completionpass{$param['module']}"] = COMPLETION_COMPLETE_PASS; 270 $params["completionfail{$param['module']}"] = COMPLETION_COMPLETE_FAIL; 271 $params["completioncomplete{$param['module']}"] = COMPLETION_COMPLETE; 272 } 273 return array($join, $where, $params); 274 } 275 } 276 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body