Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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   * @package   mod_forum
  20   * @copyright Jamie Pratt <me@jamiep.org>
  21   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  if (!defined('MOODLE_INTERNAL')) {
  25      die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
  26  }
  27  
  28  require_once ($CFG->dirroot.'/course/moodleform_mod.php');
  29  
  30  use core_grades\component_gradeitems;
  31  
  32  class mod_forum_mod_form extends moodleform_mod {
  33  
  34      function definition() {
  35          global $CFG, $COURSE, $DB;
  36  
  37          $mform    =& $this->_form;
  38  
  39  //-------------------------------------------------------------------------------
  40          $mform->addElement('header', 'general', get_string('general', 'form'));
  41  
  42          $mform->addElement('text', 'name', get_string('forumname', 'forum'), array('size'=>'64'));
  43          if (!empty($CFG->formatstringstriptags)) {
  44              $mform->setType('name', PARAM_TEXT);
  45          } else {
  46              $mform->setType('name', PARAM_CLEANHTML);
  47          }
  48          $mform->addRule('name', null, 'required', null, 'client');
  49          $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
  50  
  51          $this->standard_intro_elements(get_string('forumintro', 'forum'));
  52  
  53          $forumtypes = forum_get_forum_types();
  54          core_collator::asort($forumtypes, core_collator::SORT_STRING);
  55          $mform->addElement('select', 'type', get_string('forumtype', 'forum'), $forumtypes);
  56          $mform->addHelpButton('type', 'forumtype', 'forum');
  57          $mform->setDefault('type', 'general');
  58  
  59          $mform->addElement('header', 'availability', get_string('availability', 'forum'));
  60  
  61          $name = get_string('duedate', 'forum');
  62          $mform->addElement('date_time_selector', 'duedate', $name, array('optional' => true));
  63          $mform->addHelpButton('duedate', 'duedate', 'forum');
  64  
  65          $name = get_string('cutoffdate', 'forum');
  66          $mform->addElement('date_time_selector', 'cutoffdate', $name, array('optional' => true));
  67          $mform->addHelpButton('cutoffdate', 'cutoffdate', 'forum');
  68  
  69          // Attachments and word count.
  70          $mform->addElement('header', 'attachmentswordcounthdr', get_string('attachmentswordcount', 'forum'));
  71  
  72          $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes, 0, $CFG->forum_maxbytes);
  73          $choices[1] = get_string('uploadnotallowed');
  74          $mform->addElement('select', 'maxbytes', get_string('maxattachmentsize', 'forum'), $choices);
  75          $mform->addHelpButton('maxbytes', 'maxattachmentsize', 'forum');
  76          $mform->setDefault('maxbytes', $CFG->forum_maxbytes);
  77  
  78          $choices = array(
  79              0 => 0,
  80              1 => 1,
  81              2 => 2,
  82              3 => 3,
  83              4 => 4,
  84              5 => 5,
  85              6 => 6,
  86              7 => 7,
  87              8 => 8,
  88              9 => 9,
  89              10 => 10,
  90              20 => 20,
  91              50 => 50,
  92              100 => 100
  93          );
  94          $mform->addElement('select', 'maxattachments', get_string('maxattachments', 'forum'), $choices);
  95          $mform->addHelpButton('maxattachments', 'maxattachments', 'forum');
  96          $mform->setDefault('maxattachments', $CFG->forum_maxattachments);
  97  
  98          $mform->addElement('selectyesno', 'displaywordcount', get_string('displaywordcount', 'forum'));
  99          $mform->addHelpButton('displaywordcount', 'displaywordcount', 'forum');
 100          $mform->setDefault('displaywordcount', 0);
 101  
 102          // Subscription and tracking.
 103          $mform->addElement('header', 'subscriptionandtrackinghdr', get_string('subscriptionandtracking', 'forum'));
 104  
 105          $options = forum_get_subscriptionmode_options();
 106          $mform->addElement('select', 'forcesubscribe', get_string('subscriptionmode', 'forum'), $options);
 107          $mform->addHelpButton('forcesubscribe', 'subscriptionmode', 'forum');
 108          if (isset($CFG->forum_subscription)) {
 109              $defaultforumsubscription = $CFG->forum_subscription;
 110          } else {
 111              $defaultforumsubscription = FORUM_CHOOSESUBSCRIBE;
 112          }
 113          $mform->setDefault('forcesubscribe', $defaultforumsubscription);
 114  
 115          $options = array();
 116          $options[FORUM_TRACKING_OPTIONAL] = get_string('trackingoptional', 'forum');
 117          $options[FORUM_TRACKING_OFF] = get_string('trackingoff', 'forum');
 118          if ($CFG->forum_allowforcedreadtracking) {
 119              $options[FORUM_TRACKING_FORCED] = get_string('trackingon', 'forum');
 120          }
 121          $mform->addElement('select', 'trackingtype', get_string('trackingtype', 'forum'), $options);
 122          $mform->addHelpButton('trackingtype', 'trackingtype', 'forum');
 123          $default = $CFG->forum_trackingtype;
 124          if ((!$CFG->forum_allowforcedreadtracking) && ($default == FORUM_TRACKING_FORCED)) {
 125              $default = FORUM_TRACKING_OPTIONAL;
 126          }
 127          $mform->setDefault('trackingtype', $default);
 128  
 129          if ($CFG->enablerssfeeds && isset($CFG->forum_enablerssfeeds) && $CFG->forum_enablerssfeeds) {
 130  //-------------------------------------------------------------------------------
 131              $mform->addElement('header', 'rssheader', get_string('rss'));
 132              $choices = array();
 133              $choices[0] = get_string('none');
 134              $choices[1] = get_string('discussions', 'forum');
 135              $choices[2] = get_string('posts', 'forum');
 136              $mform->addElement('select', 'rsstype', get_string('rsstype', 'forum'), $choices);
 137              $mform->addHelpButton('rsstype', 'rsstype', 'forum');
 138              if (isset($CFG->forum_rsstype)) {
 139                  $mform->setDefault('rsstype', $CFG->forum_rsstype);
 140              }
 141  
 142              $choices = array();
 143              $choices[0] = '0';
 144              $choices[1] = '1';
 145              $choices[2] = '2';
 146              $choices[3] = '3';
 147              $choices[4] = '4';
 148              $choices[5] = '5';
 149              $choices[10] = '10';
 150              $choices[15] = '15';
 151              $choices[20] = '20';
 152              $choices[25] = '25';
 153              $choices[30] = '30';
 154              $choices[40] = '40';
 155              $choices[50] = '50';
 156              $mform->addElement('select', 'rssarticles', get_string('rssarticles'), $choices);
 157              $mform->addHelpButton('rssarticles', 'rssarticles', 'forum');
 158              $mform->hideIf('rssarticles', 'rsstype', 'eq', '0');
 159              if (isset($CFG->forum_rssarticles)) {
 160                  $mform->setDefault('rssarticles', $CFG->forum_rssarticles);
 161              }
 162          }
 163  
 164          $mform->addElement('header', 'discussionlocking', get_string('discussionlockingheader', 'forum'));
 165          $options = [
 166              0               => get_string('discussionlockingdisabled', 'forum'),
 167              1   * DAYSECS   => get_string('numday', 'core', 1),
 168              1   * WEEKSECS  => get_string('numweek', 'core', 1),
 169              2   * WEEKSECS  => get_string('numweeks', 'core', 2),
 170              30  * DAYSECS   => get_string('nummonth', 'core', 1),
 171              60  * DAYSECS   => get_string('nummonths', 'core', 2),
 172              90  * DAYSECS   => get_string('nummonths', 'core', 3),
 173              180 * DAYSECS   => get_string('nummonths', 'core', 6),
 174              1   * YEARSECS  => get_string('numyear', 'core', 1),
 175          ];
 176          $mform->addElement('select', 'lockdiscussionafter', get_string('lockdiscussionafter', 'forum'), $options);
 177          $mform->addHelpButton('lockdiscussionafter', 'lockdiscussionafter', 'forum');
 178          $mform->disabledIf('lockdiscussionafter', 'type', 'eq', 'single');
 179  
 180  //-------------------------------------------------------------------------------
 181          $mform->addElement('header', 'blockafterheader', get_string('blockafter', 'forum'));
 182          $options = array();
 183          $options[0] = get_string('blockperioddisabled','forum');
 184          $options[60*60*24]   = '1 '.get_string('day');
 185          $options[60*60*24*2] = '2 '.get_string('days');
 186          $options[60*60*24*3] = '3 '.get_string('days');
 187          $options[60*60*24*4] = '4 '.get_string('days');
 188          $options[60*60*24*5] = '5 '.get_string('days');
 189          $options[60*60*24*6] = '6 '.get_string('days');
 190          $options[60*60*24*7] = '1 '.get_string('week');
 191          $mform->addElement('select', 'blockperiod', get_string('blockperiod', 'forum'), $options);
 192          $mform->addHelpButton('blockperiod', 'blockperiod', 'forum');
 193  
 194          $mform->addElement('text', 'blockafter', get_string('blockafter', 'forum'));
 195          $mform->setType('blockafter', PARAM_INT);
 196          $mform->setDefault('blockafter', '0');
 197          $mform->addRule('blockafter', null, 'numeric', null, 'client');
 198          $mform->addHelpButton('blockafter', 'blockafter', 'forum');
 199          $mform->hideIf('blockafter', 'blockperiod', 'eq', 0);
 200  
 201          $mform->addElement('text', 'warnafter', get_string('warnafter', 'forum'));
 202          $mform->setType('warnafter', PARAM_INT);
 203          $mform->setDefault('warnafter', '0');
 204          $mform->addRule('warnafter', null, 'numeric', null, 'client');
 205          $mform->addHelpButton('warnafter', 'warnafter', 'forum');
 206          $mform->hideIf('warnafter', 'blockperiod', 'eq', 0);
 207  
 208          $coursecontext = context_course::instance($COURSE->id);
 209          // To be removed (deprecated) with MDL-67526.
 210          plagiarism_get_form_elements_module($mform, $coursecontext, 'mod_forum');
 211  
 212  //-------------------------------------------------------------------------------
 213  
 214          // Add the whole forum grading options.
 215          $this->add_forum_grade_settings($mform, 'forum');
 216  
 217          $this->standard_coursemodule_elements();
 218  //-------------------------------------------------------------------------------
 219  // buttons
 220          $this->add_action_buttons();
 221      }
 222  
 223      /**
 224       * Add the whole forum grade settings to the mform.
 225       *
 226       * @param   \mform $mform
 227       * @param   string $itemname
 228       */
 229      private function add_forum_grade_settings($mform, string $itemname) {
 230          global $COURSE;
 231  
 232          $component = "mod_{$this->_modname}";
 233          $defaultgradingvalue = 0;
 234  
 235          $itemnumber = component_gradeitems::get_itemnumber_from_itemname($component, $itemname);
 236          $gradefieldname = component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'grade');
 237          $gradecatfieldname = component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'gradecat');
 238          $gradepassfieldname = component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'gradepass');
 239          $sendstudentnotificationsfieldname = component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber,
 240                  'sendstudentnotifications');
 241  
 242          // The advancedgradingmethod is different in that it is suffixed with an area name... which is not the
 243          // itemnumber.
 244          $methodfieldname = "advancedgradingmethod_{$itemname}";
 245  
 246          $headername = "{$gradefieldname}_header";
 247          $mform->addElement('header', $headername, get_string("grade_{$itemname}_header", $component));
 248  
 249          $isupdate = !empty($this->_cm);
 250          $gradeoptions = [
 251              'isupdate' => $isupdate,
 252              'currentgrade' => false,
 253              'hasgrades' => false,
 254              'canrescale' => false,
 255              'useratings' => false,
 256          ];
 257  
 258          if ($isupdate) {
 259              $gradeitem = grade_item::fetch([
 260                  'itemtype' => 'mod',
 261                  'itemmodule' => $this->_cm->modname,
 262                  'iteminstance' => $this->_cm->instance,
 263                  'itemnumber' => $itemnumber,
 264                  'courseid' => $COURSE->id,
 265              ]);
 266              if ($gradeitem) {
 267                  $gradeoptions['currentgrade'] = $gradeitem->grademax;
 268                  $gradeoptions['currentgradetype'] = $gradeitem->gradetype;
 269                  $gradeoptions['currentscaleid'] = $gradeitem->scaleid;
 270                  $gradeoptions['hasgrades'] = $gradeitem->has_grades();
 271              }
 272          }
 273          $mform->addElement(
 274              'modgrade',
 275              $gradefieldname,
 276              get_string("{$gradefieldname}_title", $component),
 277              $gradeoptions
 278          );
 279          $mform->addHelpButton($gradefieldname, 'modgrade', 'grades');
 280          $mform->setDefault($gradefieldname, $defaultgradingvalue);
 281  
 282          if (!empty($this->current->_advancedgradingdata['methods']) && !empty($this->current->_advancedgradingdata['areas'])) {
 283              $areadata = $this->current->_advancedgradingdata['areas'][$itemname];
 284              $mform->addElement(
 285                  'select',
 286                  $methodfieldname,
 287                  get_string('gradingmethod', 'core_grading'),
 288                  $this->current->_advancedgradingdata['methods']
 289              );
 290              $mform->addHelpButton($methodfieldname, 'gradingmethod', 'core_grading');
 291              $mform->hideIf($methodfieldname, "{$gradefieldname}[modgrade_type]", 'eq', 'none');
 292          }
 293  
 294          // Grade category.
 295          $mform->addElement(
 296              'select',
 297              $gradecatfieldname,
 298              get_string('gradecategoryonmodform', 'grades'),
 299              grade_get_categories_menu($COURSE->id, $this->_outcomesused)
 300          );
 301          $mform->addHelpButton($gradecatfieldname, 'gradecategoryonmodform', 'grades');
 302          $mform->hideIf($gradecatfieldname, "{$gradefieldname}[modgrade_type]", 'eq', 'none');
 303  
 304          // Grade to pass.
 305          $mform->addElement('text', $gradepassfieldname, get_string('gradepass', 'grades'));
 306          $mform->addHelpButton($gradepassfieldname, 'gradepass', 'grades');
 307          $mform->setDefault($gradepassfieldname, '');
 308          $mform->setType($gradepassfieldname, PARAM_RAW);
 309          $mform->hideIf($gradepassfieldname, "{$gradefieldname}[modgrade_type]", 'eq', 'none');
 310  
 311          $mform->addElement(
 312                  'selectyesno',
 313                  $sendstudentnotificationsfieldname,
 314                  get_string('sendstudentnotificationsdefault', 'forum')
 315          );
 316          $mform->addHelpButton($sendstudentnotificationsfieldname, 'sendstudentnotificationsdefault', 'forum');
 317          $mform->hideIf($sendstudentnotificationsfieldname, "{$gradefieldname}[modgrade_type]", 'eq', 'none');
 318      }
 319  
 320      function definition_after_data() {
 321          parent::definition_after_data();
 322          $mform     =& $this->_form;
 323          $type      =& $mform->getElement('type');
 324          $typevalue = $mform->getElementValue('type');
 325  
 326          //we don't want to have these appear as possible selections in the form but
 327          //we want the form to display them if they are set.
 328          if ($typevalue[0]=='news') {
 329              $type->addOption(get_string('namenews', 'forum'), 'news');
 330              $mform->addHelpButton('type', 'namenews', 'forum');
 331              $type->freeze();
 332              $type->setPersistantFreeze(true);
 333          }
 334          if ($typevalue[0]=='social') {
 335              $type->addOption(get_string('namesocial', 'forum'), 'social');
 336              $type->freeze();
 337              $type->setPersistantFreeze(true);
 338          }
 339      }
 340  
 341      public function validation($data, $files) {
 342          $errors = parent::validation($data, $files);
 343  
 344          if ($data['duedate'] && $data['cutoffdate']) {
 345              if ($data['duedate'] > $data['cutoffdate']) {
 346                  $errors['cutoffdate'] = get_string('cutoffdatevalidation', 'forum');
 347              }
 348          }
 349  
 350          $this->validation_forum_grade($data, $files, $errors);
 351  
 352          return $errors;
 353      }
 354  
 355      /**
 356       * Handle definition after data for grade settings.
 357       *
 358       * @param array $data
 359       * @param array $files
 360       * @param array $errors
 361       */
 362      private function validation_forum_grade(array $data, array $files, array $errors) {
 363          global $COURSE;
 364  
 365          $mform =& $this->_form;
 366  
 367          $component = "mod_forum";
 368          $itemname = 'forum';
 369          $itemnumber = component_gradeitems::get_itemnumber_from_itemname($component, $itemname);
 370          $gradefieldname = component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'grade');
 371          $gradepassfieldname = component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'grade');
 372  
 373          $gradeitem = grade_item::fetch([
 374              'itemtype' => 'mod',
 375              'itemmodule' => $data['modulename'],
 376              'iteminstance' => $data['instance'],
 377              'itemnumber' => $itemnumber,
 378              'courseid' => $COURSE->id,
 379          ]);
 380  
 381          if ($mform->elementExists('cmidnumber') && $this->_cm) {
 382              if (!grade_verify_idnumber($data['cmidnumber'], $COURSE->id, $gradeitem, $this->_cm)) {
 383                  $errors['cmidnumber'] = get_string('idnumbertaken');
 384              }
 385          }
 386  
 387          // Check that the grade pass is a valid number.
 388          $gradepassvalid = false;
 389          if (isset($data[$gradepassfieldname])) {
 390              if (unformat_float($data[$gradepassfieldname], true) === false) {
 391                  $errors[$gradepassfieldname] = get_string('err_numeric', 'form');
 392              } else {
 393                  $gradepassvalid = true;
 394              }
 395          }
 396  
 397          // Grade to pass: ensure that the grade to pass is valid for points and scales.
 398          // If we are working with a scale, convert into a positive number for validation.
 399          if ($gradepassvalid && isset($data[$gradepassfieldname]) && (!empty($data[$gradefieldname]))) {
 400              $grade = $data[$gradefieldname];
 401              if (unformat_float($data[$gradepassfieldname]) > $grade) {
 402                  $errors[$gradepassfieldname] = get_string('gradepassgreaterthangrade', 'grades', $grade);
 403              }
 404          }
 405      }
 406  
 407      function data_preprocessing(&$default_values) {
 408          parent::data_preprocessing($default_values);
 409  
 410          // Set up the completion checkboxes which aren't part of standard data.
 411          // We also make the default value (if you turn on the checkbox) for those
 412          // numbers to be 1, this will not apply unless checkbox is ticked.
 413          $default_values['completiondiscussionsenabled']=
 414              !empty($default_values['completiondiscussions']) ? 1 : 0;
 415          if (empty($default_values['completiondiscussions'])) {
 416              $default_values['completiondiscussions']=1;
 417          }
 418          $default_values['completionrepliesenabled']=
 419              !empty($default_values['completionreplies']) ? 1 : 0;
 420          if (empty($default_values['completionreplies'])) {
 421              $default_values['completionreplies']=1;
 422          }
 423          // Tick by default if Add mode or if completion posts settings is set to 1 or more.
 424          if (empty($this->_instance) || !empty($default_values['completionposts'])) {
 425              $default_values['completionpostsenabled'] = 1;
 426          } else {
 427              $default_values['completionpostsenabled'] = 0;
 428          }
 429          if (empty($default_values['completionposts'])) {
 430              $default_values['completionposts']=1;
 431          }
 432      }
 433  
 434      /**
 435       * Add custom completion rules.
 436       *
 437       * @return array Array of string IDs of added items, empty array if none
 438       */
 439      public function add_completion_rules() {
 440          $mform =& $this->_form;
 441  
 442          $group=array();
 443          $group[] =& $mform->createElement('checkbox', 'completionpostsenabled', '', get_string('completionposts','forum'));
 444          $group[] =& $mform->createElement('text', 'completionposts', '', array('size'=>3));
 445          $mform->setType('completionposts',PARAM_INT);
 446          $mform->addGroup($group, 'completionpostsgroup', get_string('completionpostsgroup','forum'), array(' '), false);
 447          $mform->disabledIf('completionposts','completionpostsenabled','notchecked');
 448  
 449          $group=array();
 450          $group[] =& $mform->createElement('checkbox', 'completiondiscussionsenabled', '', get_string('completiondiscussions','forum'));
 451          $group[] =& $mform->createElement('text', 'completiondiscussions', '', array('size'=>3));
 452          $mform->setType('completiondiscussions',PARAM_INT);
 453          $mform->addGroup($group, 'completiondiscussionsgroup', get_string('completiondiscussionsgroup','forum'), array(' '), false);
 454          $mform->disabledIf('completiondiscussions','completiondiscussionsenabled','notchecked');
 455  
 456          $group=array();
 457          $group[] =& $mform->createElement('checkbox', 'completionrepliesenabled', '', get_string('completionreplies','forum'));
 458          $group[] =& $mform->createElement('text', 'completionreplies', '', array('size'=>3));
 459          $mform->setType('completionreplies',PARAM_INT);
 460          $mform->addGroup($group, 'completionrepliesgroup', get_string('completionrepliesgroup','forum'), array(' '), false);
 461          $mform->disabledIf('completionreplies','completionrepliesenabled','notchecked');
 462  
 463          return array('completiondiscussionsgroup','completionrepliesgroup','completionpostsgroup');
 464      }
 465  
 466      function completion_rule_enabled($data) {
 467          return (!empty($data['completiondiscussionsenabled']) && $data['completiondiscussions']!=0) ||
 468              (!empty($data['completionrepliesenabled']) && $data['completionreplies']!=0) ||
 469              (!empty($data['completionpostsenabled']) && $data['completionposts']!=0);
 470      }
 471  
 472      /**
 473       * Return submitted data if properly submitted or returns NULL if validation fails or
 474       * if there is no submitted data.
 475       *
 476       * Do not override this method, override data_postprocessing() instead.
 477       *
 478       * @return object submitted data; NULL if not valid or not submitted or cancelled
 479       */
 480      public function get_data() {
 481          $data = parent::get_data();
 482          if ($data) {
 483              $itemname = 'forum';
 484              $component = 'mod_forum';
 485              $gradepassfieldname = component_gradeitems::get_field_name_for_itemname($component, $itemname, 'gradepass');
 486  
 487              // Convert the grade pass value - we may be using a language which uses commas,
 488              // rather than decimal points, in numbers. These need to be converted so that
 489              // they can be added to the DB.
 490              if (isset($data->{$gradepassfieldname})) {
 491                  $data->{$gradepassfieldname} = unformat_float($data->{$gradepassfieldname});
 492              }
 493          }
 494  
 495          return $data;
 496      }
 497  
 498      /**
 499       * Allows module to modify the data returned by form get_data().
 500       * This method is also called in the bulk activity completion form.
 501       *
 502       * Only available on moodleform_mod.
 503       *
 504       * @param stdClass $data the form data to be modified.
 505       */
 506      public function data_postprocessing($data) {
 507          parent::data_postprocessing($data);
 508          // Turn off completion settings if the checkboxes aren't ticked
 509          if (!empty($data->completionunlocked)) {
 510              $autocompletion = !empty($data->completion) && $data->completion==COMPLETION_TRACKING_AUTOMATIC;
 511              if (empty($data->completiondiscussionsenabled) || !$autocompletion) {
 512                  $data->completiondiscussions = 0;
 513              }
 514              if (empty($data->completionrepliesenabled) || !$autocompletion) {
 515                  $data->completionreplies = 0;
 516              }
 517              if (empty($data->completionpostsenabled) || !$autocompletion) {
 518                  $data->completionposts = 0;
 519              }
 520          }
 521      }
 522  }