PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/badges/criteria/award_criteria_activity.php

https://gitlab.com/unofficial-mirrors/moodle
PHP | 271 lines | 178 code | 33 blank | 60 comment | 35 complexity | b10d325f4b4911961c562efae8048a24 MD5 | raw file
  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. * This file contains the activity badge award criteria type class
  18. *
  19. * @package core
  20. * @subpackage badges
  21. * @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. * @author Yuliya Bozhko <yuliya.bozhko@totaralms.com>
  24. */
  25. defined('MOODLE_INTERNAL') || die();
  26. require_once($CFG->libdir . '/completionlib.php');
  27. /**
  28. * Badge award criteria -- award on activity completion
  29. *
  30. */
  31. class award_criteria_activity extends award_criteria {
  32. /* @var int Criteria [BADGE_CRITERIA_TYPE_ACTIVITY] */
  33. public $criteriatype = BADGE_CRITERIA_TYPE_ACTIVITY;
  34. private $courseid;
  35. private $course;
  36. public $required_param = 'module';
  37. public $optional_params = array('bydate');
  38. public function __construct($record) {
  39. global $DB;
  40. parent::__construct($record);
  41. $this->course = $DB->get_record_sql('SELECT c.id, c.enablecompletion, c.cacherev, c.startdate
  42. FROM {badge} b LEFT JOIN {course} c ON b.courseid = c.id
  43. WHERE b.id = :badgeid ', array('badgeid' => $this->badgeid), MUST_EXIST);
  44. // 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.
  45. if (empty($this->course->id)) {
  46. $this->course = get_course(SITEID);
  47. }
  48. $this->courseid = $this->course->id;
  49. }
  50. /**
  51. * Gets the module instance from the database and returns it.
  52. * If no module instance exists this function returns false.
  53. *
  54. * @return stdClass|bool
  55. */
  56. private function get_mod_instance($cmid) {
  57. global $DB;
  58. $rec = $DB->get_record_sql("SELECT md.name
  59. FROM {course_modules} cm,
  60. {modules} md
  61. WHERE cm.id = ? AND
  62. md.id = cm.module", array($cmid));
  63. if ($rec) {
  64. return get_coursemodule_from_id($rec->name, $cmid);
  65. } else {
  66. return null;
  67. }
  68. }
  69. /**
  70. * Get criteria description for displaying to users
  71. *
  72. * @return string
  73. */
  74. public function get_details($short = '') {
  75. global $DB, $OUTPUT;
  76. $output = array();
  77. foreach ($this->params as $p) {
  78. $mod = self::get_mod_instance($p['module']);
  79. if (!$mod) {
  80. $str = $OUTPUT->error_text(get_string('error:nosuchmod', 'badges'));
  81. } else {
  82. $str = html_writer::tag('b', '"' . get_string('modulename', $mod->modname) . ' - ' . $mod->name . '"');
  83. if (isset($p['bydate'])) {
  84. $str .= get_string('criteria_descr_bydate', 'badges', userdate($p['bydate'], get_string('strftimedate', 'core_langconfig')));
  85. }
  86. }
  87. $output[] = $str;
  88. }
  89. if ($short) {
  90. return implode(', ', $output);
  91. } else {
  92. return html_writer::alist($output, array(), 'ul');
  93. }
  94. }
  95. /**
  96. * Add appropriate new criteria options to the form
  97. *
  98. */
  99. public function get_options(&$mform) {
  100. $none = true;
  101. $existing = array();
  102. $missing = array();
  103. $course = $this->course;
  104. $info = new completion_info($course);
  105. $mods = $info->get_activities();
  106. $mids = array_keys($mods);
  107. if ($this->id !== 0) {
  108. $existing = array_keys($this->params);
  109. $missing = array_diff($existing, $mids);
  110. }
  111. if (!empty($missing)) {
  112. $mform->addElement('header', 'category_errors', get_string('criterror', 'badges'));
  113. $mform->addHelpButton('category_errors', 'criterror', 'badges');
  114. foreach ($missing as $m) {
  115. $this->config_options($mform, array('id' => $m, 'checked' => true,
  116. 'name' => get_string('error:nosuchmod', 'badges'), 'error' => true));
  117. $none = false;
  118. }
  119. }
  120. if (!empty($mods)) {
  121. $mform->addElement('header', 'first_header', $this->get_title());
  122. foreach ($mods as $mod) {
  123. $checked = false;
  124. if (in_array($mod->id, $existing)) {
  125. $checked = true;
  126. }
  127. $param = array('id' => $mod->id,
  128. 'checked' => $checked,
  129. 'name' => get_string('modulename', $mod->modname) . ' - ' . $mod->name,
  130. 'error' => false
  131. );
  132. if ($this->id !== 0 && isset($this->params[$mod->id]['bydate'])) {
  133. $param['bydate'] = $this->params[$mod->id]['bydate'];
  134. }
  135. if ($this->id !== 0 && isset($this->params[$mod->id]['grade'])) {
  136. $param['grade'] = $this->params[$mod->id]['grade'];
  137. }
  138. $this->config_options($mform, $param);
  139. $none = false;
  140. }
  141. }
  142. // Add aggregation.
  143. if (!$none) {
  144. $mform->addElement('header', 'aggregation', get_string('method', 'badges'));
  145. $agg = array();
  146. $agg[] =& $mform->createElement('radio', 'agg', '', get_string('allmethodactivity', 'badges'), 1);
  147. $agg[] =& $mform->createElement('radio', 'agg', '', get_string('anymethodactivity', 'badges'), 2);
  148. $mform->addGroup($agg, 'methodgr', '', array('<br/>'), false);
  149. if ($this->id !== 0) {
  150. $mform->setDefault('agg', $this->method);
  151. } else {
  152. $mform->setDefault('agg', BADGE_CRITERIA_AGGREGATION_ANY);
  153. }
  154. }
  155. return array($none, get_string('error:noactivities', 'badges'));
  156. }
  157. /**
  158. * Review this criteria and decide if it has been completed
  159. *
  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.
  163. *
  164. * @return bool Whether criteria is complete
  165. */
  166. public function review($userid, $filtered = false) {
  167. $completionstates = array(COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS);
  168. if ($this->course->startdate > time()) {
  169. return false;
  170. }
  171. $info = new completion_info($this->course);
  172. $overall = false;
  173. foreach ($this->params as $param) {
  174. $cm = new stdClass();
  175. $cm->id = $param['module'];
  176. $data = $info->get_data($cm, false, $userid);
  177. $check_date = true;
  178. if (isset($param['bydate'])) {
  179. $date = $data->timemodified;
  180. $check_date = ($date <= $param['bydate']);
  181. }
  182. if ($this->method == BADGE_CRITERIA_AGGREGATION_ALL) {
  183. if (in_array($data->completionstate, $completionstates) && $check_date) {
  184. $overall = true;
  185. continue;
  186. } else {
  187. return false;
  188. }
  189. } else {
  190. if (in_array($data->completionstate, $completionstates) && $check_date) {
  191. return true;
  192. } else {
  193. $overall = false;
  194. continue;
  195. }
  196. }
  197. }
  198. return $overall;
  199. }
  200. /**
  201. * Returns array with sql code and parameters returning all ids
  202. * of users who meet this particular criterion.
  203. *
  204. * @return array list($join, $where, $params)
  205. */
  206. public function get_completed_criteria_sql() {
  207. $join = '';
  208. $where = '';
  209. $params = array();
  210. if ($this->method == BADGE_CRITERIA_AGGREGATION_ANY) {
  211. foreach ($this->params as $param) {
  212. $moduledata[] = " cmc.coursemoduleid = :completedmodule{$param['module']} ";
  213. $params["completedmodule{$param['module']}"] = $param['module'];
  214. }
  215. if (!empty($moduledata)) {
  216. $extraon = implode(' OR ', $moduledata);
  217. $join = " JOIN {course_modules_completion} cmc ON cmc.userid = u.id AND
  218. ( cmc.completionstate = :completionpass OR cmc.completionstate = :completioncomplete ) AND ({$extraon})";
  219. $params["completionpass"] = COMPLETION_COMPLETE_PASS;
  220. $params["completioncomplete"] = COMPLETION_COMPLETE;
  221. }
  222. return array($join, $where, $params);
  223. } else {
  224. foreach ($this->params as $param) {
  225. $join .= " LEFT JOIN {course_modules_completion} cmc{$param['module']} ON
  226. cmc{$param['module']}.userid = u.id AND
  227. cmc{$param['module']}.coursemoduleid = :completedmodule{$param['module']} AND
  228. ( cmc{$param['module']}.completionstate = :completionpass{$param['module']} OR
  229. cmc{$param['module']}.completionstate = :completioncomplete{$param['module']} )";
  230. $where .= " AND cmc{$param['module']}.coursemoduleid IS NOT NULL ";
  231. $params["completedmodule{$param['module']}"] = $param['module'];
  232. $params["completionpass{$param['module']}"] = COMPLETION_COMPLETE_PASS;
  233. $params["completioncomplete{$param['module']}"] = COMPLETION_COMPLETE;
  234. }
  235. return array($join, $where, $params);
  236. }
  237. }
  238. }