Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 402 and 403]
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 * Base form for changing completion rules 19 * 20 * @package core_completion 21 * @copyright 2017 Marina Glancy 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die; 26 27 require_once($CFG->libdir.'/formslib.php'); 28 require_once($CFG->libdir.'/completionlib.php'); 29 require_once($CFG->dirroot.'/course/modlib.php'); 30 31 /** 32 * Base form for changing completion rules. Used in bulk editing activity completion and editing default activity completion 33 * 34 * @package core_completion 35 * @copyright 2017 Marina Glancy 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 abstract class core_completion_edit_base_form extends moodleform { 39 /** @var moodleform_mod Do not use directly, call $this->get_module_form() */ 40 protected $_moduleform = null; 41 /** @var bool */ 42 protected $hascustomrules = false; 43 /** @var stdClass */ 44 protected $course; 45 46 /** 47 * Returns list of types of selected module types 48 * 49 * @return array modname=>modfullname 50 */ 51 abstract protected function get_module_names(); 52 53 /** 54 * Returns true if all selected modules support tracking view. 55 * 56 * @return bool 57 */ 58 protected function support_views() { 59 foreach ($this->get_module_names() as $modname => $modfullname) { 60 if (!plugin_supports('mod', $modname, FEATURE_COMPLETION_TRACKS_VIEWS, false)) { 61 return false; 62 } 63 } 64 return true; 65 } 66 67 /** 68 * Returns true if all selected modules support grading. 69 * 70 * @return bool 71 */ 72 protected function support_grades() { 73 foreach ($this->get_module_names() as $modname => $modfullname) { 74 if (!plugin_supports('mod', $modname, FEATURE_GRADE_HAS_GRADE, false)) { 75 return false; 76 } 77 } 78 return true; 79 } 80 81 /** 82 * Returns an instance of component-specific module form for the first selected module 83 * 84 * @return moodleform_mod|null 85 */ 86 abstract protected function get_module_form(); 87 88 /** 89 * If all selected modules are of the same module type, adds custom completion rules from this module type 90 * 91 * @return array 92 */ 93 protected function add_custom_completion_rules() { 94 $modnames = array_keys($this->get_module_names()); 95 if (count($modnames) != 1 || !plugin_supports('mod', $modnames[0], FEATURE_COMPLETION_HAS_RULES, false)) { 96 return []; 97 } 98 99 try { 100 // Add completion rules from the module form to this form. 101 $moduleform = $this->get_module_form(); 102 $moduleform->_form = $this->_form; 103 if ($customcompletionelements = $moduleform->add_completion_rules()) { 104 $this->hascustomrules = true; 105 } 106 return $customcompletionelements; 107 } catch (Exception $e) { 108 debugging('Could not add custom completion rule of module ' . $modnames[0] . 109 ' to this form, this has to be fixed by the developer', DEBUG_DEVELOPER); 110 return []; 111 } 112 } 113 114 /** 115 * Checks if at least one of the custom completion rules is enabled 116 * 117 * @param array $data Input data (not yet validated) 118 * @return bool True if one or more rules is enabled, false if none are; 119 * default returns false 120 */ 121 protected function completion_rule_enabled($data) { 122 if ($this->hascustomrules) { 123 return $this->get_module_form()->completion_rule_enabled($data); 124 } 125 return false; 126 } 127 128 /** 129 * Returns list of modules that have automatic completion rules that are not shown on this form 130 * (because they are not present in at least one other selected module). 131 * 132 * @return array 133 */ 134 protected function get_modules_with_hidden_rules() { 135 $modnames = $this->get_module_names(); 136 if (count($modnames) <= 1) { 137 // No rules definitions conflicts if there is only one module type. 138 return []; 139 } 140 141 $conflicts = []; 142 143 if (!$this->support_views()) { 144 // If we don't display views rule but at least one module supports it - we have conflicts. 145 foreach ($modnames as $modname => $modfullname) { 146 if (empty($conflicts[$modname]) && plugin_supports('mod', $modname, FEATURE_COMPLETION_TRACKS_VIEWS, false)) { 147 $conflicts[$modname] = $modfullname; 148 } 149 } 150 } 151 152 if (!$this->support_grades()) { 153 // If we don't display grade rule but at least one module supports it - we have conflicts. 154 foreach ($modnames as $modname => $modfullname) { 155 if (empty($conflicts[$modname]) && plugin_supports('mod', $modname, FEATURE_GRADE_HAS_GRADE, false)) { 156 $conflicts[$modname] = $modfullname; 157 } 158 } 159 } 160 161 foreach ($modnames as $modname => $modfullname) { 162 // We do not display any custom completion rules, find modules that define them and add to conflicts list. 163 if (empty($conflicts[$modname]) && plugin_supports('mod', $modname, FEATURE_COMPLETION_HAS_RULES, false)) { 164 $conflicts[$modname] = $modfullname; 165 } 166 } 167 168 return $conflicts; 169 } 170 171 /** 172 * Form definition 173 */ 174 public function definition() { 175 $mform = $this->_form; 176 177 // Course id. 178 $mform->addElement('hidden', 'id', $this->course->id); 179 $mform->setType('id', PARAM_INT); 180 181 // Unlock completion automatically (this element can be used in validation). 182 $mform->addElement('hidden', 'completionunlocked', 1); 183 $mform->setType('completionunlocked', PARAM_INT); 184 185 $mform->addElement('select', 'completion', get_string('completion', 'completion'), 186 array(COMPLETION_TRACKING_NONE => get_string('completion_none', 'completion'), 187 COMPLETION_TRACKING_MANUAL => get_string('completion_manual', 'completion'))); 188 $mform->addHelpButton('completion', 'completion', 'completion'); 189 $mform->setDefault('completion', COMPLETION_TRACKING_NONE); 190 191 // Automatic completion once you view it. 192 $autocompletionpossible = false; 193 if ($this->support_views()) { 194 $mform->addElement('advcheckbox', 'completionview', get_string('completionview', 'completion'), 195 get_string('completionview_desc', 'completion')); 196 $mform->disabledIf('completionview', 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); 197 $autocompletionpossible = true; 198 } 199 200 // Automatic completion once it's graded. 201 if ($this->support_grades()) { 202 $group = []; 203 $group[] = $mform->createElement('advcheckbox', 'completionusegrade', get_string('completionusegrade', 'completion'), 204 get_string('completionusegrade_desc', 'completion')); 205 $mform->addHelpButton('completionusegrade', 'completionusegrade', 'completion', '', true); 206 207 $group[] = $mform->createElement('advcheckbox', 'completionpassgrade', get_string('completionpassgrade', 'completion'), 208 get_string('completionpassgrade_desc', 'completion')); 209 $mform->addHelpButton('completionpassgrade', 'completionpassgrade', 'completion', '', true); 210 $mform->disabledIf('completionpassgrade', 'completionusegrade', 'notchecked'); 211 212 $mform->addGroup($group, 'completionpassgroup', get_string('completionpassgrade', 'completion'), ' ', false); 213 $mform->disabledIf('completionpassgroup', 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); 214 215 $autocompletionpossible = true; 216 } 217 218 // Automatic completion according to module-specific rules. 219 foreach ($this->add_custom_completion_rules() as $element) { 220 $mform->disabledIf($element, 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); 221 $autocompletionpossible = true; 222 } 223 224 // Automatic option only appears if possible. 225 if ($autocompletionpossible) { 226 $mform->getElement('completion')->addOption( 227 get_string('completion_automatic', 'completion'), 228 COMPLETION_TRACKING_AUTOMATIC); 229 } 230 231 // Completion expected at particular date? (For progress tracking). 232 $mform->addElement('date_time_selector', 'completionexpected', 233 get_string('completionexpected', 'completion'), ['optional' => true]); 234 $mform->addHelpButton('completionexpected', 'completionexpected', 'completion'); 235 $mform->disabledIf('completionexpected', 'completion', 'eq', COMPLETION_TRACKING_NONE); 236 237 if ($conflicts = $this->get_modules_with_hidden_rules()) { 238 $mform->addElement('static', 'qwerty', '', get_string('hiddenrules', 'completion', join(', ', $conflicts))); 239 } 240 241 $this->add_action_buttons(); 242 } 243 244 /** 245 * Form validation 246 * 247 * @param array $data array of ("fieldname"=>value) of submitted data 248 * @param array $files array of uploaded files "element_name"=>tmp_file_path 249 * @return array of "element_name"=>"error_description" if there are errors, 250 * or an empty array if everything is OK (true allowed for backwards compatibility too). 251 */ 252 public function validation($data, $files) { 253 $errors = parent::validation($data, $files); 254 255 // Completion: Don't let them choose automatic completion without turning 256 // on some conditions. 257 if (array_key_exists('completion', $data) && 258 $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) { 259 if (empty($data['completionview']) && empty($data['completionusegrade']) && empty($data['completionpassgrade']) && 260 !$this->completion_rule_enabled($data)) { 261 $errors['completion'] = get_string('badautocompletion', 'completion'); 262 } 263 } 264 265 return $errors; 266 } 267 268 /** 269 * Returns if this form has custom completion rules. This is only possible if all selected modules have the same 270 * module type and this module type supports custom completion rules 271 * 272 * @return bool 273 */ 274 public function has_custom_completion_rules() { 275 return $this->hascustomrules; 276 } 277 278 /** 279 * Return submitted data if properly submitted or returns NULL if validation fails or 280 * if there is no submitted data. 281 * 282 * @return object submitted data; NULL if not valid or not submitted or cancelled 283 */ 284 public function get_data() { 285 $data = parent::get_data(); 286 if ($data && $this->hascustomrules) { 287 $this->get_module_form()->data_postprocessing($data); 288 } 289 return $data; 290 } 291 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body