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 * Classes to manage manual badge award. 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 require_once($CFG->libdir . '/badgeslib.php'); 30 require_once($CFG->dirroot . '/user/selector/lib.php'); 31 32 abstract class badge_award_selector_base extends user_selector_base { 33 34 /** 35 * The id of the badge this selector is being used for 36 * @var int 37 */ 38 protected $badgeid = null; 39 /** 40 * The context of the badge this selector is being used for 41 * @var object 42 */ 43 protected $context = null; 44 /** 45 * The id of the role of badge issuer in current context 46 * @var int 47 */ 48 protected $issuerrole = null; 49 /** 50 * The id of badge issuer 51 * @var int 52 */ 53 protected $issuerid = null; 54 55 /** 56 * The return address. Accepts either a string or a moodle_url. 57 * @var string $url 58 */ 59 public $url; 60 61 /** 62 * The current group being displayed. 63 * @var int $currentgroup 64 */ 65 public $currentgroup; 66 67 /** 68 * Constructor method 69 * @param string $name 70 * @param array $options 71 */ 72 public function __construct($name, array $options) { 73 $options['accesscontext'] = $options['context']; 74 parent::__construct($name, $options); 75 if (isset($options['context'])) { 76 if ($options['context'] instanceof context_system) { 77 // If it is a site badge, we need to get context of frontpage. 78 $this->context = context_course::instance(SITEID); 79 } else { 80 $this->context = $options['context']; 81 } 82 } 83 if (isset($options['badgeid'])) { 84 $this->badgeid = $options['badgeid']; 85 } 86 if (isset($options['issuerid'])) { 87 $this->issuerid = $options['issuerid']; 88 } 89 if (isset($options['issuerrole'])) { 90 $this->issuerrole = $options['issuerrole']; 91 } 92 if (isset($options['url'])) { 93 $this->url = $options['url']; 94 } 95 if (isset($options['currentgroup'])) { 96 $this->currentgroup = $options['currentgroup']; 97 } else { 98 // Returns group active in course, changes the group by default if 'group' page param present. 99 $this->currentgroup = groups_get_course_group($COURSE, true); 100 } 101 } 102 103 /** 104 * Returns an array of options to seralise and store for searches 105 * 106 * @return array 107 */ 108 protected function get_options() { 109 global $CFG; 110 $options = parent::get_options(); 111 $options['file'] = 'badges/lib/awardlib.php'; 112 $options['context'] = $this->context; 113 $options['badgeid'] = $this->badgeid; 114 $options['issuerid'] = $this->issuerid; 115 $options['issuerrole'] = $this->issuerrole; 116 // These will be used to filter potential badge recipients when searching. 117 $options['currentgroup'] = $this->currentgroup; 118 return $options; 119 } 120 121 /** 122 * Restricts the selection of users to display, according to the groups they belong. 123 * 124 * @return array 125 */ 126 protected function get_groups_sql() { 127 $groupsql = ''; 128 $groupwheresql = ''; 129 $groupwheresqlparams = array(); 130 if ($this->currentgroup) { 131 $groupsql = ' JOIN {groups_members} gm ON gm.userid = u.id '; 132 $groupwheresql = ' AND gm.groupid = :gr_grpid '; 133 $groupwheresqlparams = array('gr_grpid' => $this->currentgroup); 134 } 135 return array($groupsql, $groupwheresql, $groupwheresqlparams); 136 } 137 } 138 139 /** 140 * A user selector control for potential users to award badge 141 */ 142 class badge_potential_users_selector extends badge_award_selector_base { 143 const MAX_USERS_PER_PAGE = 100; 144 145 /** 146 * Existing recipients 147 */ 148 protected $existingrecipients = array(); 149 150 /** 151 * Finds all potential badge recipients 152 * 153 * Potential badge recipients are all enroled users 154 * who haven't got a badge from current issuer role. 155 * 156 * @param string $search 157 * @return array 158 */ 159 public function find_users($search) { 160 global $DB; 161 162 $whereconditions = array(); 163 list($wherecondition, $params) = $this->search_sql($search, 'u'); 164 if ($wherecondition) { 165 $whereconditions[] = $wherecondition; 166 } 167 168 $existingids = array(); 169 foreach ($this->existingrecipients as $group) { 170 foreach ($group as $user) { 171 $existingids[] = $user->id; 172 } 173 } 174 if ($existingids) { 175 list($usertest, $userparams) = $DB->get_in_or_equal($existingids, SQL_PARAMS_NAMED, 'ex', false); 176 $whereconditions[] = 'u.id ' . $usertest; 177 $params = array_merge($params, $userparams); 178 } 179 180 if ($whereconditions) { 181 $wherecondition = ' WHERE ' . implode(' AND ', $whereconditions); 182 } 183 184 list($groupsql, $groupwheresql, $groupwheresqlparams) = $this->get_groups_sql(); 185 186 list($esql, $eparams) = get_enrolled_sql($this->context, 'moodle/badges:earnbadge', 0, true); 187 $params = array_merge($params, $eparams, $groupwheresqlparams); 188 189 $fields = 'SELECT ' . $this->required_fields_sql('u'); 190 $countfields = 'SELECT COUNT(u.id)'; 191 192 $params['badgeid'] = $this->badgeid; 193 $params['issuerrole'] = $this->issuerrole; 194 195 $sql = " FROM {user} u JOIN ($esql) je ON je.id = u.id 196 LEFT JOIN {badge_manual_award} bm 197 ON (bm.recipientid = u.id AND bm.badgeid = :badgeid AND bm.issuerrole = :issuerrole) 198 $groupsql 199 $wherecondition AND bm.id IS NULL 200 $groupwheresql"; 201 202 list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext); 203 $order = ' ORDER BY ' . $sort; 204 205 if (!$this->is_validating()) { 206 $potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params); 207 if ($potentialmemberscount > self::MAX_USERS_PER_PAGE) { 208 return $this->too_many_results($search, $potentialmemberscount); 209 } 210 } 211 212 $availableusers = $DB->get_records_sql($fields . $sql . $order, array_merge($params, $sortparams)); 213 214 if (empty($availableusers)) { 215 return array(); 216 } 217 218 return array(get_string('potentialrecipients', 'badges') => $availableusers); 219 } 220 221 /** 222 * Sets the existing recipients 223 * @param array $users 224 */ 225 public function set_existing_recipients(array $users) { 226 $this->existingrecipients = $users; 227 } 228 } 229 230 /** 231 * A user selector control for existing users to award badge 232 */ 233 class badge_existing_users_selector extends badge_award_selector_base { 234 235 /** 236 * Finds all users who already have been awarded a badge by current role 237 * 238 * @param string $search 239 * @return array 240 */ 241 public function find_users($search) { 242 global $DB; 243 list($wherecondition, $params) = $this->search_sql($search, 'u'); 244 $params['badgeid'] = $this->badgeid; 245 $params['issuerrole'] = $this->issuerrole; 246 247 list($esql, $eparams) = get_enrolled_sql($this->context, 'moodle/badges:earnbadge', 0, true); 248 $fields = $this->required_fields_sql('u'); 249 list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext); 250 251 list($groupsql, $groupwheresql, $groupwheresqlparams) = $this->get_groups_sql(); 252 253 $params = array_merge($params, $eparams, $sortparams, $groupwheresqlparams); 254 $recipients = $DB->get_records_sql("SELECT $fields 255 FROM {user} u 256 JOIN ($esql) je ON je.id = u.id 257 JOIN {badge_manual_award} s ON s.recipientid = u.id 258 $groupsql 259 WHERE $wherecondition AND s.badgeid = :badgeid AND s.issuerrole = :issuerrole 260 $groupwheresql 261 ORDER BY $sort", $params); 262 263 return array(get_string('existingrecipients', 'badges') => $recipients); 264 } 265 } 266 267 function process_manual_award($recipientid, $issuerid, $issuerrole, $badgeid) { 268 global $DB; 269 $params = array( 270 'badgeid' => $badgeid, 271 'issuerid' => $issuerid, 272 'issuerrole' => $issuerrole, 273 'recipientid' => $recipientid 274 ); 275 276 if (!$DB->record_exists('badge_manual_award', $params)) { 277 $award = new stdClass(); 278 $award->badgeid = $badgeid; 279 $award->issuerid = $issuerid; 280 $award->issuerrole = $issuerrole; 281 $award->recipientid = $recipientid; 282 $award->datemet = time(); 283 if ($DB->insert_record('badge_manual_award', $award)) { 284 return true; 285 } 286 } 287 return false; 288 } 289 290 /** 291 * Manually revoke awarded badges. 292 * 293 * @param int $recipientid 294 * @param int $issuerid 295 * @param int $issuerrole 296 * @param int $badgeid 297 * @return bool 298 */ 299 function process_manual_revoke($recipientid, $issuerid, $issuerrole, $badgeid) { 300 global $DB; 301 $params = array( 302 'badgeid' => $badgeid, 303 'issuerid' => $issuerid, 304 'issuerrole' => $issuerrole, 305 'recipientid' => $recipientid 306 ); 307 if ($DB->record_exists('badge_manual_award', $params)) { 308 if ($DB->delete_records('badge_manual_award', array('badgeid' => $badgeid, 309 'issuerid' => $issuerid, 310 'recipientid' => $recipientid)) 311 && $DB->delete_records('badge_issued', array('badgeid' => $badgeid, 312 'userid' => $recipientid))) { 313 314 // Trigger event, badge revoked. 315 $badge = new \badge($badgeid); 316 $eventparams = array( 317 'objectid' => $badgeid, 318 'relateduserid' => $recipientid, 319 'context' => $badge->get_context() 320 ); 321 $event = \core\event\badge_revoked::create($eventparams); 322 $event->trigger(); 323 324 return true; 325 } 326 } else { 327 throw new moodle_exception('error:badgenotfound', 'badges'); 328 } 329 return false; 330 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body