Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 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 $mform->addElement('advcheckbox', 'completionusegrade', get_string('completionusegrade', 'completion'), 203 get_string('completionusegrade_desc', 'completion')); 204 $mform->disabledIf('completionusegrade', 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); 205 $mform->addHelpButton('completionusegrade', 'completionusegrade', 'completion'); 206 $autocompletionpossible = true; 207 } 208 209 // Automatic completion according to module-specific rules. 210 foreach ($this->add_custom_completion_rules() as $element) { 211 $mform->disabledIf($element, 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); 212 $autocompletionpossible = true; 213 } 214 215 // Automatic option only appears if possible. 216 if ($autocompletionpossible) { 217 $mform->getElement('completion')->addOption( 218 get_string('completion_automatic', 'completion'), 219 COMPLETION_TRACKING_AUTOMATIC); 220 } 221 222 // Completion expected at particular date? (For progress tracking). 223 $mform->addElement('date_time_selector', 'completionexpected', 224 get_string('completionexpected', 'completion'), ['optional' => true]); 225 $mform->addHelpButton('completionexpected', 'completionexpected', 'completion'); 226 $mform->disabledIf('completionexpected', 'completion', 'eq', COMPLETION_TRACKING_NONE); 227 228 if ($conflicts = $this->get_modules_with_hidden_rules()) { 229 $mform->addElement('static', 'qwerty', '', get_string('hiddenrules', 'completion', join(', ', $conflicts))); 230 } 231 232 $this->add_action_buttons(); 233 } 234 235 /** 236 * Form validation 237 * 238 * @param array $data array of ("fieldname"=>value) of submitted data 239 * @param array $files array of uploaded files "element_name"=>tmp_file_path 240 * @return array of "element_name"=>"error_description" if there are errors, 241 * or an empty array if everything is OK (true allowed for backwards compatibility too). 242 */ 243 public function validation($data, $files) { 244 $errors = parent::validation($data, $files); 245 246 // Completion: Don't let them choose automatic completion without turning 247 // on some conditions. 248 if (array_key_exists('completion', $data) && 249 $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) { 250 if (empty($data['completionview']) && empty($data['completionusegrade']) && 251 !$this->completion_rule_enabled($data)) { 252 $errors['completion'] = get_string('badautocompletion', 'completion'); 253 } 254 } 255 256 return $errors; 257 } 258 259 /** 260 * Returns if this form has custom completion rules. This is only possible if all selected modules have the same 261 * module type and this module type supports custom completion rules 262 * 263 * @return bool 264 */ 265 public function has_custom_completion_rules() { 266 return $this->hascustomrules; 267 } 268 269 /** 270 * Return submitted data if properly submitted or returns NULL if validation fails or 271 * if there is no submitted data. 272 * 273 * @return object submitted data; NULL if not valid or not submitted or cancelled 274 */ 275 public function get_data() { 276 $data = parent::get_data(); 277 if ($data && $this->hascustomrules) { 278 $this->get_module_form()->data_postprocessing($data); 279 } 280 return $data; 281 } 282 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body