2 // This file is part of Moodle - http://moodle.org/
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.
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/>.
18 * This file contains the profile completion badge award criteria type class
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");
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();
43 * Add appropriate new criteria options to the form
46 public function get_options(&$mform) {
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";
64 $cfields = $DB->get_records_sql($sql);
65 $cfids = array_map(function($o) {
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));
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) {
88 if (in_array($field, $existing)) {
91 $this->config_options($mform, array('id' => $field, 'checked' => $checked, 'name' => get_user_field_name($field), 'error' => 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
));
103 if (in_array($field->fieldid
, $existing)) {
106 $this->config_options($mform, array('id' => $field->fieldid
, 'checked' => $checked, 'name' => $field->name
, 'error' => false));
113 $mform->addElement('header', 'aggregation', get_string('method', 'badges'));
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
);
122 $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY
);
126 return array($none, get_string('noparamstoadd', 'badges'));
130 * Get criteria details for displaying to users
134 public function get_details($short = '') {
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']));
141 $str = get_user_field_name($p['field']);
144 $output[] = $OUTPUT->error_text(get_string('error:nosuchfield', 'badges'));
151 return implode(', ', $output);
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) {
169 // Users were already filtered by criteria completion, no checks required.
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";
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";
192 $whereparts[] = $DB->sql_isnotempty('u', "u.{$param['field']}", false, true);
197 $sqlparams['userid'] = $userid;
200 $where = " AND (" . implode($rule, $whereparts) . ")";
204 $sql = "SELECT 1 FROM {user} u " . $join . " WHERE u.id = :userid $where";
205 $overall = $DB->record_exists_sql($sql, $sqlparams);
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() {
220 $whereparts = 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";
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";
237 $whereparts[] = $DB->sql_isnotempty('u', "u.{$param['field']}", false, true);
243 $where = " AND (" . implode($rule, $whereparts) . ")";
247 return array($join, $where, $params);