89897ea01c4b59c3353571c9f5edbb9d03f46880
[moodle.git] / badges / criteria / award_criteria_course.php
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/>.
17 /**
18  * This file contains the course completion 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  */
27 defined('MOODLE_INTERNAL') || die();
28 require_once($CFG->libdir . '/completionlib.php');
29 require_once($CFG->dirroot . '/grade/querylib.php');
30 require_once($CFG->libdir . '/gradelib.php');
32 /**
33  * Badge award criteria -- award on course completion
34  *
35  */
36 class award_criteria_course extends award_criteria {
38     /* @var int Criteria [BADGE_CRITERIA_TYPE_COURSE] */
39     public $criteriatype = BADGE_CRITERIA_TYPE_COURSE;
41     private $courseid;
42     private $coursestartdate;
44     public $required_param = 'course';
45     public $optional_params = array('grade', 'bydate');
47     public function __construct($record) {
48         global $DB;
49         parent::__construct($record);
51         $course = $DB->get_record_sql('SELECT b.courseid, c.startdate
52                         FROM {badge} b INNER JOIN {course} c ON b.courseid = c.id
53                         WHERE b.id = :badgeid ', array('badgeid' => $this->badgeid));
54         $this->courseid = $course->courseid;
55         $this->coursestartdate = $course->startdate;
56     }
58     /**
59      * Add appropriate form elements to the criteria form
60      *
61      * @param moodleform $mform  Moodle forms object
62      * @param stdClass $data details of various modules
63      */
64     public function config_form_criteria($data) {
65         global $OUTPUT;
67         $editurl = new moodle_url('/badges/criteria_settings.php', array('badgeid' => $this->badgeid, 'edit' => true, 'type' => $this->criteriatype, 'crit' => $this->id));
68         $deleteurl = new moodle_url('/badges/criteria_action.php', array('badgeid' => $this->badgeid, 'delete' => true, 'type' => $this->criteriatype));
69         $editaction = $OUTPUT->action_icon($editurl, new pix_icon('t/edit', get_string('edit')), null, array('class' => 'criteria-action'));
70         $deleteaction = $OUTPUT->action_icon($deleteurl, new pix_icon('t/delete', get_string('delete')), null, array('class' => 'criteria-action'));
72         echo $OUTPUT->box_start();
73         if (!$data->is_locked() && !$data->is_active()) {
74             echo $OUTPUT->box($deleteaction . $editaction, array('criteria-header'));
75         }
76         echo $OUTPUT->heading($this->get_title() . $OUTPUT->help_icon('criteria_' . $this->criteriatype, 'badges'), 3, 'main help');
78         if (!empty($this->description)) {
79             echo $OUTPUT->box(
80                 format_text($this->description, FORMAT_HTML, array('context' => context_course::instance($this->courseid))),
81                 'criteria-description'
82                 );
83         }
85         if (!empty($this->params)) {
86             echo $OUTPUT->box(get_string('criteria_descr_' . $this->criteriatype, 'badges') . $this->get_details(), array('clearfix'));
87         }
88         echo $OUTPUT->box_end();
89     }
91     /**
92      * Get criteria details for displaying to users
93      *
94      * @return string
95      */
96     public function get_details($short = '') {
97         global $DB;
98         $param = reset($this->params);
100         $course = $DB->get_record('course', array('id' => $param['course']));
101         if (!$course) {
102             $str = $OUTPUT->error_text(get_string('error:nosuchcourse', 'badges'));
103         } else {
104             $options = array('context' => context_course::instance($course->id));
105             $str = html_writer::tag('b', '"' . format_string($course->fullname, true, $options) . '"');
106             if (isset($param['bydate'])) {
107                 $str .= get_string('criteria_descr_bydate', 'badges', userdate($param['bydate'], get_string('strftimedate', 'core_langconfig')));
108             }
109             if (isset($param['grade'])) {
110                 $str .= get_string('criteria_descr_grade', 'badges', $param['grade']);
111             }
112         }
113         return $str;
114     }
116     /**
117      * Add appropriate new criteria options to the form
118      *
119      */
120     public function get_options(&$mform) {
121         global $DB;
122         $param = array();
124         if ($this->id !== 0) {
125             $param = reset($this->params);
126         } else {
127             $param['course'] = $mform->getElementValue('course');
128             $mform->removeElement('course');
129         }
130         $course = $DB->get_record('course', array('id' => $param['course']));
132         if (!($course->enablecompletion == COMPLETION_ENABLED)) {
133             $none = true;
134             $message = get_string('completionnotenabled', 'badges');
135         } else {
136             $mform->addElement('header', 'criteria_course', $this->get_title());
137             $mform->addHelpButton('criteria_course', 'criteria_' . $this->criteriatype, 'badges');
138             $parameter = array();
139             $parameter[] =& $mform->createElement('static', 'mgrade_', null, get_string('mingrade', 'badges'));
140             $parameter[] =& $mform->createElement('text', 'grade_' . $param['course'], '', array('size' => '5'));
141             $parameter[] =& $mform->createElement('static', 'complby_' . $param['course'], null, get_string('bydate', 'badges'));
142             $parameter[] =& $mform->createElement('date_selector', 'bydate_' . $param['course'], '', array('optional' => true));
143             $mform->setType('grade_' . $param['course'], PARAM_INT);
144             $mform->addGroup($parameter, 'param_' . $param['course'], '', array(' '), false);
146             $mform->disabledIf('bydate_' . $param['course'] . '[day]', 'bydate_' . $param['course'] . '[enabled]', 'notchecked');
147             $mform->disabledIf('bydate_' . $param['course'] . '[month]', 'bydate_' . $param['course'] . '[enabled]', 'notchecked');
148             $mform->disabledIf('bydate_' . $param['course'] . '[year]', 'bydate_' . $param['course'] . '[enabled]', 'notchecked');
150             // Set existing values.
151             if (isset($param['bydate'])) {
152                 $mform->setDefault('bydate_' . $param['course'], $param['bydate']);
153             }
155             if (isset($param['grade'])) {
156                 $mform->setDefault('grade_' . $param['course'], $param['grade']);
157             }
159             // Add hidden elements.
160             $mform->addElement('hidden', 'course_' . $course->id, $course->id);
161             $mform->setType('course_' . $course->id, PARAM_INT);
162             $mform->addElement('hidden', 'agg', BADGE_CRITERIA_AGGREGATION_ALL);
163             $mform->setType('agg', PARAM_INT);
165             $none = false;
166             $message = '';
167         }
168         return array($none, $message);
169     }
171     /**
172      * Review this criteria and decide if it has been completed
173      *
174      * @param int $userid User whose criteria completion needs to be reviewed.
175      * @param bool $filtered An additional parameter indicating that user list
176      *        has been reduced and some expensive checks can be skipped.
177      *
178      * @return bool Whether criteria is complete
179      */
180     public function review($userid, $filtered = false) {
181         $course = new stdClass();
182         $course->id = $this->courseid;
184         if ($this->coursestartdate > time()) {
185             return false;
186         }
188         $info = new completion_info($course);
190         foreach ($this->params as $param) {
191             $check_grade = true;
192             $check_date = true;
194             if (isset($param['grade'])) {
195                 $grade = grade_get_course_grade($userid, $course->id);
196                 $check_grade = ($grade->grade >= $param['grade']);
197             }
199             if (!$filtered && isset($param['bydate'])) {
200                 $cparams = array(
201                         'userid' => $userid,
202                         'course' => $course->id,
203                 );
204                 $completion = new completion_completion($cparams);
205                 $date = $completion->timecompleted;
206                 $check_date = ($date <= $param['bydate']);
207             }
209             if ($info->is_course_complete($userid) && $check_grade && $check_date) {
210                 return true;
211             }
212         }
214         return false;
215     }
217     /**
218      * Returns array with sql code and parameters returning all ids
219      * of users who meet this particular criterion.
220      *
221      * @return array list($join, $where, $params)
222      */
223     public function get_completed_criteria_sql() {
224         // We have only one criterion here, so taking the first one.
225         $coursecriteria = reset($this->params);
227         $join = " LEFT JOIN {course_completions} cc ON cc.userid = u.id AND cc.timecompleted > 0";
228         $where = ' AND cc.course = :courseid ';
229         $params['courseid'] = $this->courseid;
231         // Add by date parameter.
232         if (isset($param['bydate'])) {
233             $where .= ' AND cc.timecompleted <= :completebydate';
234             $params['completebydate'] = $coursecriteria['bydate'];
235         }
237         return array($join, $where, $params);
238     }