Merge branch 'MDL-62663' of https://github.com/andrewhancox/moodle
[moodle.git] / badges / criteria / award_criteria_profile.php
blobda76bc8747426ce0423a233a515e3b979dd803cc
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.
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/>.
17 /**
18 * This file contains the profile completion badge award criteria type class
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>
27 defined('MOODLE_INTERNAL') || die();
28 require_once($CFG->dirroot . "/user/lib.php");
30 /**
31 * Profile completion badge award criteria
34 class award_criteria_profile extends award_criteria {
36 /* @var int Criteria [BADGE_CRITERIA_TYPE_PROFILE] */
37 public $criteriatype = BADGE_CRITERIA_TYPE_PROFILE;
39 public $required_param = 'field';
40 public $optional_params = array();
42 /**
43 * Add appropriate new criteria options to the form
46 public function get_options(&$mform) {
47 global $DB;
49 $none = true;
50 $existing = array();
51 $missing = array();
53 // Note: cannot use user_get_default_fields() here because it is not possible to decide which fields user can modify.
54 $dfields = array('firstname', 'lastname', 'email', 'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo',
55 'aim', 'msn', 'department', 'institution', 'description', 'picture', 'city', 'url', 'country');
57 $sql = "SELECT uf.id as fieldid, uf.name as name, ic.id as categoryid, ic.name as categoryname, uf.datatype
58 FROM {user_info_field} uf
59 JOIN {user_info_category} ic
60 ON uf.categoryid = ic.id AND uf.visible <> 0
61 ORDER BY ic.sortorder ASC, uf.sortorder ASC";
63 // Get custom fields.
64 $cfields = $DB->get_records_sql($sql);
65 $cfids = array_map(function($o) {
66 return $o->fieldid;
67 }, $cfields);
69 if ($this->id !== 0) {
70 $existing = array_keys($this->params);
71 $missing = array_diff($existing, array_merge($dfields, $cfids));
74 if (!empty($missing)) {
75 $mform->addElement('header', 'category_errors', get_string('criterror', 'badges'));
76 $mform->addHelpButton('category_errors', 'criterror', 'badges');
77 foreach ($missing as $m) {
78 $this->config_options($mform, array('id' => $m, 'checked' => true, 'name' => get_string('error:nosuchfield', 'badges'), 'error' => true));
79 $none = false;
83 if (!empty($dfields)) {
84 $mform->addElement('header', 'first_header', $this->get_title());
85 $mform->addHelpButton('first_header', 'criteria_' . $this->criteriatype, 'badges');
86 foreach ($dfields as $field) {
87 $checked = false;
88 if (in_array($field, $existing)) {
89 $checked = true;
91 $this->config_options($mform, array('id' => $field, 'checked' => $checked, 'name' => get_user_field_name($field), 'error' => false));
92 $none = false;
96 if (!empty($cfields)) {
97 foreach ($cfields as $field) {
98 if (!isset($currentcat) || $currentcat != $field->categoryid) {
99 $currentcat = $field->categoryid;
100 $mform->addElement('header', 'category_' . $currentcat, format_string($field->categoryname));
102 $checked = false;
103 if (in_array($field->fieldid, $existing)) {
104 $checked = true;
106 $this->config_options($mform, array('id' => $field->fieldid, 'checked' => $checked, 'name' => $field->name, 'error' => false));
107 $none = false;
111 // Add aggregation.
112 if (!$none) {
113 $mform->addElement('header', 'aggregation', get_string('method', 'badges'));
114 $agg = array();
115 $agg[] =& $mform->createElement('radio', 'agg', '', get_string('allmethodprofile', 'badges'), 1);
116 $agg[] =& $mform->createElement('static', 'none_break', null, '<br/>');
117 $agg[] =& $mform->createElement('radio', 'agg', '', get_string('anymethodprofile', 'badges'), 2);
118 $mform->addGroup($agg, 'methodgr', '', array(' '), false);
119 if ($this->id !== 0) {
120 $mform->setDefault('agg', $this->method);
121 } else {
122 $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY);
126 return array($none, get_string('noparamstoadd', 'badges'));
130 * Get criteria details for displaying to users
132 * @return string
134 public function get_details($short = '') {
135 global $DB, $OUTPUT;
136 $output = array();
137 foreach ($this->params as $p) {
138 if (is_numeric($p['field'])) {
139 $str = $DB->get_field('user_info_field', 'name', array('id' => $p['field']));
140 } else {
141 $str = get_user_field_name($p['field']);
143 if (!$str) {
144 $output[] = $OUTPUT->error_text(get_string('error:nosuchfield', 'badges'));
145 } else {
146 $output[] = $str;
150 if ($short) {
151 return implode(', ', $output);
152 } else {
153 return html_writer::alist($output, array(), 'ul');
158 * Review this criteria and decide if it has been completed
160 * @param int $userid User whose criteria completion needs to be reviewed.
161 * @param bool $filtered An additional parameter indicating that user list
162 * has been reduced and some expensive checks can be skipped.
164 * @return bool Whether criteria is complete
166 public function review($userid, $filtered = false) {
167 global $DB;
169 // Users were already filtered by criteria completion, no checks required.
170 if ($filtered) {
171 return true;
174 $join = '';
175 $whereparts = array();
176 $sqlparams = array();
177 $rule = ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) ? ' OR ' : ' AND ';
179 foreach ($this->params as $param) {
180 if (is_numeric($param['field'])) {
181 // This is a custom field.
182 $idx = count($whereparts) + 1;
183 $join .= " LEFT JOIN {user_info_data} uid{$idx} ON uid{$idx}.userid = u.id AND uid{$idx}.fieldid = :fieldid{$idx} ";
184 $sqlparams["fieldid{$idx}"] = $param['field'];
185 $whereparts[] = "uid{$idx}.id IS NOT NULL";
186 } else {
187 // This is a field from {user} table.
188 if ($param['field'] == 'picture') {
189 // The picture field is numeric and requires special handling.
190 $whereparts[] = "u.{$param['field']} != 0";
191 } else {
192 $whereparts[] = $DB->sql_isnotempty('u', "u.{$param['field']}", false, true);
197 $sqlparams['userid'] = $userid;
199 if ($whereparts) {
200 $where = " AND (" . implode($rule, $whereparts) . ")";
201 } else {
202 $where = '';
204 $sql = "SELECT 1 FROM {user} u " . $join . " WHERE u.id = :userid $where";
205 $overall = $DB->record_exists_sql($sql, $sqlparams);
207 return $overall;
211 * Returns array with sql code and parameters returning all ids
212 * of users who meet this particular criterion.
214 * @return array list($join, $where, $params)
216 public function get_completed_criteria_sql() {
217 global $DB;
219 $join = '';
220 $whereparts = array();
221 $params = array();
222 $rule = ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) ? ' OR ' : ' AND ';
224 foreach ($this->params as $param) {
225 if (is_numeric($param['field'])) {
226 // This is a custom field.
227 $idx = count($whereparts);
228 $join .= " LEFT JOIN {user_info_data} uid{$idx} ON uid{$idx}.userid = u.id AND uid{$idx}.fieldid = :fieldid{$idx} ";
229 $params["fieldid{$idx}"] = $param['field'];
230 $whereparts[] = "uid{$idx}.id IS NOT NULL";
231 } else {
232 // This is a field from {user} table.
233 if ($param['field'] == 'picture') {
234 // The picture field is numeric and requires special handling.
235 $whereparts[] = "u.{$param['field']} != 0";
236 } else {
237 $whereparts[] = $DB->sql_isnotempty('u', "u.{$param['field']}", false, true);
242 if ($whereparts) {
243 $where = " AND (" . implode($rule, $whereparts) . ")";
244 } else {
245 $where = '';
247 return array($join, $where, $params);