Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 39 and 402]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * Edit course completion settings - the form definition.
  20   *
  21   * @package     core_completion
  22   * @category    completion
  23   * @copyright   2009 Catalyst IT Ltd
  24   * @author      Aaron Barnes <aaronb@catalyst.net.nz>
  25   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  26   */
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  require_once($CFG->libdir.'/formslib.php');
  31  require_once($CFG->libdir.'/completionlib.php');
  32  
  33  /**
  34   * Defines the course completion settings form.
  35   */
  36  class course_completion_form extends moodleform {
  37  
  38      /**
  39       * Defines the form fields.
  40       */
  41      public function definition() {
  42          global $USER, $CFG, $DB;
  43  
  44          $courseconfig = get_config('moodlecourse');
  45          $mform = $this->_form;
  46          $course = $this->_customdata['course'];
  47          $completion = new completion_info($course);
  48  
  49          $params = array(
  50              'course'  => $course->id
  51          );
  52  
  53          // Check if there are existing criteria completions.
  54          if ($completion->is_course_locked()) {
  55              $mform->addElement('header', 'completionsettingslocked', get_string('completionsettingslocked', 'completion'));
  56              $mform->addElement('static', '', '', get_string('err_settingslocked', 'completion'));
  57              $mform->addElement('submit', 'settingsunlock', get_string('unlockcompletiondelete', 'completion'));
  58          }
  59  
  60          // Get array of all available aggregation methods.
  61          $aggregation_methods = $completion->get_aggregation_methods();
  62  
  63          // Overall criteria aggregation.
  64          $mform->addElement('header', 'overallcriteria', get_string('general', 'core_form'));
  65          // Map aggregation methods to context-sensitive human readable dropdown menu.
  66          $overallaggregationmenu = array();
  67          foreach ($aggregation_methods as $methodcode => $methodname) {
  68              if ($methodcode === COMPLETION_AGGREGATION_ALL) {
  69                  $overallaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('overallaggregation_all', 'core_completion');
  70              } else if ($methodcode === COMPLETION_AGGREGATION_ANY) {
  71                  $overallaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('overallaggregation_any', 'core_completion');
  72              } else {
  73                  $overallaggregationmenu[$methodcode] = $methodname;
  74              }
  75          }
  76          $mform->addElement('select', 'overall_aggregation', get_string('overallaggregation', 'core_completion'), $overallaggregationmenu);
  77          $mform->setDefault('overall_aggregation', $completion->get_aggregation_method());
  78  
  79          // Activity completion criteria
  80          $label = get_string('coursecompletioncondition', 'core_completion', get_string('activitiescompleted', 'core_completion'));
  81          $mform->addElement('header', 'activitiescompleted', $label);
  82          // Get the list of currently specified conditions and expand the section if some are found.
  83          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_ACTIVITY);
  84          if (!empty($current)) {
  85              $mform->setExpanded('activitiescompleted');
  86          }
  87  
  88          $activities = $completion->get_activities();
  89          if (!empty($activities)) {
  90  
  91              if (!$completion->is_course_locked()) {
  92                  $this->add_checkbox_controller(1, null, null, 0);
  93              }
  94              foreach ($activities as $activity) {
  95                  $params_a = array('moduleinstance' => $activity->id);
  96                  $criteria = new completion_criteria_activity(array_merge($params, $params_a));
  97                  $criteria->config_form_display($mform, $activity);
  98              }
  99              $mform->addElement('static', 'criteria_role_note', '', get_string('activitiescompletednote', 'core_completion'));
 100  
 101              if (count($activities) > 1) {
 102                  // Map aggregation methods to context-sensitive human readable dropdown menu.
 103                  $activityaggregationmenu = array();
 104                  foreach ($aggregation_methods as $methodcode => $methodname) {
 105                      if ($methodcode === COMPLETION_AGGREGATION_ALL) {
 106                          $activityaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('activityaggregation_all', 'core_completion');
 107                      } else if ($methodcode === COMPLETION_AGGREGATION_ANY) {
 108                          $activityaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('activityaggregation_any', 'core_completion');
 109                      } else {
 110                          $activityaggregationmenu[$methodcode] = $methodname;
 111                      }
 112                  }
 113                  $mform->addElement('select', 'activity_aggregation', get_string('activityaggregation', 'core_completion'), $activityaggregationmenu);
 114                  $mform->setDefault('activity_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ACTIVITY));
 115              }
 116  
 117          } else {
 118              $mform->addElement('static', 'noactivities', '', get_string('err_noactivities', 'completion'));
 119          }
 120  
 121          // Course prerequisite completion criteria.
 122          $label = get_string('coursecompletioncondition', 'core_completion', get_string('dependenciescompleted', 'core_completion'));
 123          $mform->addElement('header', 'courseprerequisites', $label);
 124          // Get the list of currently specified conditions and expand the section if some are found.
 125          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_COURSE);
 126          if (!empty($current)) {
 127              $mform->setExpanded('courseprerequisites');
 128          }
 129  
 130          // Get applicable courses (prerequisites).
 131          $hasselectablecourses = core_course_category::search_courses(['onlywithcompletion' => true], ['limit' => 2]);
 132          unset($hasselectablecourses[$course->id]);
 133          if ($hasselectablecourses) {
 134              // Show multiselect box.
 135              $mform->addElement('course', 'criteria_course', get_string('coursesavailable', 'completion'),
 136                  array('multiple' => 'multiple', 'onlywithcompletion' => true, 'exclude' => $course->id));
 137              $mform->setType('criteria_course', PARAM_INT);
 138  
 139              $selectedcourses = $DB->get_fieldset_select('course_completion_criteria', 'courseinstance',
 140                  'course = :course AND criteriatype = :type', ['course' => $course->id, 'type' => COMPLETION_CRITERIA_TYPE_COURSE]);
 141              $mform->setDefault('criteria_course', $selectedcourses);
 142  
 143              // Map aggregation methods to context-sensitive human readable dropdown menu.
 144              $courseaggregationmenu = array();
 145              foreach ($aggregation_methods as $methodcode => $methodname) {
 146                  if ($methodcode === COMPLETION_AGGREGATION_ALL) {
 147                      $courseaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('courseaggregation_all', 'core_completion');
 148                  } else if ($methodcode === COMPLETION_AGGREGATION_ANY) {
 149                      $courseaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('courseaggregation_any', 'core_completion');
 150                  } else {
 151                      $courseaggregationmenu[$methodcode] = $methodname;
 152                  }
 153              }
 154              $mform->addElement('select', 'course_aggregation', get_string('courseaggregation', 'core_completion'), $courseaggregationmenu);
 155              $mform->setDefault('course_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_COURSE));
 156          } else {
 157              $mform->addElement('static', 'nocourses', '', get_string('err_nocourses', 'completion'));
 158          }
 159  
 160          // Completion on date
 161          $label = get_string('coursecompletioncondition', 'core_completion', get_string('completionondate', 'core_completion'));
 162          $mform->addElement('header', 'date', $label);
 163          // Expand the condition section if it is currently enabled.
 164          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_DATE);
 165          if (!empty($current)) {
 166              $mform->setExpanded('date');
 167          }
 168          $criteria = new completion_criteria_date($params);
 169          $criteria->config_form_display($mform);
 170  
 171          // Completion after enrolment duration
 172          $label = get_string('coursecompletioncondition', 'core_completion', get_string('enrolmentduration', 'core_completion'));
 173          $mform->addElement('header', 'duration', $label);
 174          // Expand the condition section if it is currently enabled.
 175          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_DURATION);
 176          if (!empty($current)) {
 177              $mform->setExpanded('duration');
 178          }
 179          $criteria = new completion_criteria_duration($params);
 180          $criteria->config_form_display($mform);
 181  
 182          // Completion on unenrolment
 183          $label = get_string('coursecompletioncondition', 'core_completion', get_string('unenrolment', 'core_completion'));
 184          $mform->addElement('header', 'unenrolment', $label);
 185          // Expand the condition section if it is currently enabled.
 186          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_UNENROL);
 187          if (!empty($current)) {
 188              $mform->setExpanded('unenrolment');
 189          }
 190          $criteria = new completion_criteria_unenrol($params);
 191          $criteria->config_form_display($mform);
 192  
 193          // Completion on course grade
 194          $label = get_string('coursecompletioncondition', 'core_completion', get_string('coursegrade', 'core_completion'));
 195          $mform->addElement('header', 'grade', $label);
 196          // Expand the condition section if it is currently enabled.
 197          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_GRADE);
 198          if (!empty($current)) {
 199              $mform->setExpanded('grade');
 200          }
 201          $course_grade = $DB->get_field('grade_items', 'gradepass', array('courseid' => $course->id, 'itemtype' => 'course'));
 202          if (!$course_grade) {
 203              $course_grade = '0.00000';
 204          }
 205          $criteria = new completion_criteria_grade($params);
 206          $criteria->config_form_display($mform, $course_grade);
 207  
 208          // Manual self completion
 209          $label = get_string('coursecompletioncondition', 'core_completion', get_string('manualselfcompletion', 'core_completion'));
 210          $mform->addElement('header', 'manualselfcompletion', $label);
 211          // Expand the condition section if it is currently enabled.
 212          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_SELF);
 213          if (!empty($current)) {
 214              $mform->setExpanded('manualselfcompletion');
 215          }
 216          $criteria = new completion_criteria_self($params);
 217          $criteria->config_form_display($mform);
 218          $mform->addElement('static', 'criteria_self_note', '', get_string('manualselfcompletionnote', 'core_completion'));
 219  
 220          // Role completion criteria
 221          $label = get_string('coursecompletioncondition', 'core_completion', get_string('manualcompletionby', 'core_completion'));
 222          $mform->addElement('header', 'roles', $label);
 223          // Expand the condition section if it is currently enabled.
 224          $current = $completion->get_criteria(COMPLETION_CRITERIA_TYPE_ROLE);
 225          if (!empty($current)) {
 226              $mform->setExpanded('roles');
 227          }
 228          $roles = get_roles_with_capability('moodle/course:markcomplete', CAP_ALLOW, context_course::instance($course->id, IGNORE_MISSING));
 229  
 230          if (!empty($roles)) {
 231              foreach ($roles as $role) {
 232                  $params_a = array('role' => $role->id);
 233                  $criteria = new completion_criteria_role(array_merge($params, $params_a));
 234                  $criteria->config_form_display($mform, $role);
 235              }
 236              $mform->addElement('static', 'criteria_role_note', '', get_string('manualcompletionbynote', 'core_completion'));
 237              // Map aggregation methods to context-sensitive human readable dropdown menu.
 238              $roleaggregationmenu = array();
 239              foreach ($aggregation_methods as $methodcode => $methodname) {
 240                  if ($methodcode === COMPLETION_AGGREGATION_ALL) {
 241                      $roleaggregationmenu[COMPLETION_AGGREGATION_ALL] = get_string('roleaggregation_all', 'core_completion');
 242                  } else if ($methodcode === COMPLETION_AGGREGATION_ANY) {
 243                      $roleaggregationmenu[COMPLETION_AGGREGATION_ANY] = get_string('roleaggregation_any', 'core_completion');
 244                  } else {
 245                      $roleaggregationmenu[$methodcode] = $methodname;
 246                  }
 247              }
 248              $mform->addElement('select', 'role_aggregation', get_string('roleaggregation', 'core_completion'), $roleaggregationmenu);
 249              $mform->setDefault('role_aggregation', $completion->get_aggregation_method(COMPLETION_CRITERIA_TYPE_ROLE));
 250  
 251          } else {
 252              $mform->addElement('static', 'noroles', '', get_string('err_noroles', 'completion'));
 253          }
 254  
 255          // Add common action buttons.
 256          $this->add_action_buttons();
 257  
 258          // Add hidden fields.
 259          $mform->addElement('hidden', 'id', $course->id);
 260          $mform->setType('id', PARAM_INT);
 261  
 262          // If the criteria are locked, freeze values and submit button.
 263          if ($completion->is_course_locked()) {
 264              $except = array('settingsunlock');
 265              $mform->hardFreezeAllVisibleExcept($except);
 266              $mform->addElement('cancel');
 267          }
 268      }
 269  
 270      /**
 271       * Form validation
 272       *
 273       * @param array $data
 274       * @param array $files
 275       * @return array
 276       */
 277      public function validation($data, $files) {
 278          $errors = [];
 279  
 280          if (!isset($data['criteria_course']) || $data['criteria_course'] === 0) {
 281              return $errors;
 282          }
 283  
 284          foreach ($data['criteria_course'] as $courseid) {
 285              $course = get_course($courseid);
 286              $completioninfo = new completion_info($course);
 287  
 288              if (! $completioninfo->is_enabled()) {
 289                  $errors[] = get_string('completionnotenabledforcourse', 'completion');
 290                  break;
 291              }
 292          }
 293  
 294          return $errors;
 295      }
 296  }