Ejemplo n.º 1
0
/**
 * Update a course.
 *
 * Please note this functions does not verify any access control,
 * the calling code is responsible for all validation (usually it is the form definition).
 *
 * @param object $data  - all the data needed for an entry in the 'course' table
 * @param array $editoroptions course description editor options
 * @return void
 */
function update_course($data, $editoroptions = NULL)
{
    global $DB, $CFG;
    $data->timemodified = time();
    // Prevent changes on front page course.
    if ($data->id == SITEID) {
        throw new moodle_exception('invalidcourse', 'error');
    }
    $oldcourse = course_get_format($data->id)->get_course();
    $context = context_course::instance($oldcourse->id);
    if ($editoroptions) {
        $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0);
    }
    if ($overviewfilesoptions = course_overviewfiles_options($data->id)) {
        $data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0);
    }
    // Check we don't have a duplicate shortname.
    if (!empty($data->shortname) && $oldcourse->shortname != $data->shortname) {
        if ($DB->record_exists_sql('SELECT id from {course} WHERE shortname = ? AND id <> ?', array($data->shortname, $data->id))) {
            throw new moodle_exception('shortnametaken', '', '', $data->shortname);
        }
    }
    // Check we don't have a duplicate idnumber.
    if (!empty($data->idnumber) && $oldcourse->idnumber != $data->idnumber) {
        if ($DB->record_exists_sql('SELECT id from {course} WHERE idnumber = ? AND id <> ?', array($data->idnumber, $data->id))) {
            throw new moodle_exception('courseidnumbertaken', '', '', $data->idnumber);
        }
    }
    if ($errorcode = course_validate_dates((array) $data)) {
        throw new moodle_exception($errorcode);
    }
    if (!isset($data->category) or empty($data->category)) {
        // prevent nulls and 0 in category field
        unset($data->category);
    }
    $changesincoursecat = $movecat = (isset($data->category) and $oldcourse->category != $data->category);
    if (!isset($data->visible)) {
        // data not from form, add missing visibility info
        $data->visible = $oldcourse->visible;
    }
    if ($data->visible != $oldcourse->visible) {
        // reset the visibleold flag when manually hiding/unhiding course
        $data->visibleold = $data->visible;
        $changesincoursecat = true;
    } else {
        if ($movecat) {
            $newcategory = $DB->get_record('course_categories', array('id' => $data->category));
            if (empty($newcategory->visible)) {
                // make sure when moving into hidden category the course is hidden automatically
                $data->visible = 0;
            }
        }
    }
    // Update with the new data
    $DB->update_record('course', $data);
    // make sure the modinfo cache is reset
    rebuild_course_cache($data->id);
    // update course format options with full course data
    course_get_format($data->id)->update_course_format_options($data, $oldcourse);
    $course = $DB->get_record('course', array('id' => $data->id));
    if ($movecat) {
        $newparent = context_coursecat::instance($course->category);
        $context->update_moved($newparent);
    }
    $fixcoursesortorder = $movecat || isset($data->sortorder) && $oldcourse->sortorder != $data->sortorder;
    if ($fixcoursesortorder) {
        fix_course_sortorder();
    }
    // purge appropriate caches in case fix_course_sortorder() did not change anything
    cache_helper::purge_by_event('changesincourse');
    if ($changesincoursecat) {
        cache_helper::purge_by_event('changesincoursecat');
    }
    // Test for and remove blocks which aren't appropriate anymore
    blocks_remove_inappropriate($course);
    // Save any custom role names.
    save_local_role_names($course->id, $data);
    // update enrol settings
    enrol_course_updated(false, $course, $data);
    // Update course tags.
    if (isset($data->tags)) {
        core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
    }
    // Trigger a course updated event.
    $event = \core\event\course_updated::create(array('objectid' => $course->id, 'context' => context_course::instance($course->id), 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname)));
    $event->set_legacy_logdata(array($course->id, 'course', 'update', 'edit.php?id=' . $course->id, $course->id));
    $event->trigger();
    if ($oldcourse->format !== $course->format) {
        // Remove all options stored for the previous format
        // We assume that new course format migrated everything it needed watching trigger
        // 'course_updated' and in method format_XXX::update_course_format_options()
        $DB->delete_records('course_format_options', array('courseid' => $course->id, 'format' => $oldcourse->format));
    }
}
Ejemplo n.º 2
0
 /**
  * Validation.
  *
  * @param array $data
  * @param array $files
  * @return array the errors that were found
  */
 public function validation($data, $files)
 {
     global $DB;
     $errors = parent::validation($data, $files);
     if ($errorcode = course_validate_dates($data['defaults'])) {
         $errors['defaults[enddate]'] = get_string($errorcode, 'error');
     }
     return $errors;
 }
Ejemplo n.º 3
0
 /**
  * Validates and prepares the data.
  *
  * @return bool false is any error occured.
  */
 public function prepare()
 {
     global $DB, $SITE;
     $this->prepared = true;
     // Validate the shortname.
     if (!empty($this->shortname) || is_numeric($this->shortname)) {
         if ($this->shortname !== clean_param($this->shortname, PARAM_TEXT)) {
             $this->error('invalidshortname', new lang_string('invalidshortname', 'tool_uploadcourse'));
             return false;
         }
     }
     $exists = $this->exists();
     // Do we want to delete the course?
     if ($this->options['delete']) {
         if (!$exists) {
             $this->error('cannotdeletecoursenotexist', new lang_string('cannotdeletecoursenotexist', 'tool_uploadcourse'));
             return false;
         } else {
             if (!$this->can_delete()) {
                 $this->error('coursedeletionnotallowed', new lang_string('coursedeletionnotallowed', 'tool_uploadcourse'));
                 return false;
             }
         }
         $this->do = self::DO_DELETE;
         return true;
     }
     // Can we create/update the course under those conditions?
     if ($exists) {
         if ($this->mode === tool_uploadcourse_processor::MODE_CREATE_NEW) {
             $this->error('courseexistsanduploadnotallowed', new lang_string('courseexistsanduploadnotallowed', 'tool_uploadcourse'));
             return false;
         } else {
             if ($this->can_update()) {
                 // We can never allow for any front page changes!
                 if ($this->shortname == $SITE->shortname) {
                     $this->error('cannotupdatefrontpage', new lang_string('cannotupdatefrontpage', 'tool_uploadcourse'));
                     return false;
                 }
             }
         }
     } else {
         if (!$this->can_create()) {
             $this->error('coursedoesnotexistandcreatenotallowed', new lang_string('coursedoesnotexistandcreatenotallowed', 'tool_uploadcourse'));
             return false;
         }
     }
     // Basic data.
     $coursedata = array();
     foreach ($this->rawdata as $field => $value) {
         if (!in_array($field, self::$validfields)) {
             continue;
         } else {
             if ($field == 'shortname') {
                 // Let's leave it apart from now, use $this->shortname only.
                 continue;
             }
         }
         $coursedata[$field] = $value;
     }
     $mode = $this->mode;
     $updatemode = $this->updatemode;
     $usedefaults = $this->can_use_defaults();
     // Resolve the category, and fail if not found.
     $errors = array();
     $catid = tool_uploadcourse_helper::resolve_category($this->rawdata, $errors);
     if (empty($errors)) {
         $coursedata['category'] = $catid;
     } else {
         foreach ($errors as $key => $message) {
             $this->error($key, $message);
         }
         return false;
     }
     // If the course does not exist, or will be forced created.
     if (!$exists || $mode === tool_uploadcourse_processor::MODE_CREATE_ALL) {
         // Mandatory fields upon creation.
         $errors = array();
         foreach (self::$mandatoryfields as $field) {
             if ((!isset($coursedata[$field]) || $coursedata[$field] === '') && (!isset($this->defaults[$field]) || $this->defaults[$field] === '')) {
                 $errors[] = $field;
             }
         }
         if (!empty($errors)) {
             $this->error('missingmandatoryfields', new lang_string('missingmandatoryfields', 'tool_uploadcourse', implode(', ', $errors)));
             return false;
         }
     }
     // Should the course be renamed?
     if (!empty($this->options['rename']) || is_numeric($this->options['rename'])) {
         if (!$this->can_update()) {
             $this->error('canonlyrenameinupdatemode', new lang_string('canonlyrenameinupdatemode', 'tool_uploadcourse'));
             return false;
         } else {
             if (!$exists) {
                 $this->error('cannotrenamecoursenotexist', new lang_string('cannotrenamecoursenotexist', 'tool_uploadcourse'));
                 return false;
             } else {
                 if (!$this->can_rename()) {
                     $this->error('courserenamingnotallowed', new lang_string('courserenamingnotallowed', 'tool_uploadcourse'));
                     return false;
                 } else {
                     if ($this->options['rename'] !== clean_param($this->options['rename'], PARAM_TEXT)) {
                         $this->error('invalidshortname', new lang_string('invalidshortname', 'tool_uploadcourse'));
                         return false;
                     } else {
                         if ($this->exists($this->options['rename'])) {
                             $this->error('cannotrenameshortnamealreadyinuse', new lang_string('cannotrenameshortnamealreadyinuse', 'tool_uploadcourse'));
                             return false;
                         } else {
                             if (isset($coursedata['idnumber']) && $DB->count_records_select('course', 'idnumber = :idn AND shortname != :sn', array('idn' => $coursedata['idnumber'], 'sn' => $this->shortname)) > 0) {
                                 $this->error('cannotrenameidnumberconflict', new lang_string('cannotrenameidnumberconflict', 'tool_uploadcourse'));
                                 return false;
                             }
                         }
                     }
                 }
             }
         }
         $coursedata['shortname'] = $this->options['rename'];
         $this->status('courserenamed', new lang_string('courserenamed', 'tool_uploadcourse', array('from' => $this->shortname, 'to' => $coursedata['shortname'])));
     }
     // Should we generate a shortname?
     if (empty($this->shortname) && !is_numeric($this->shortname)) {
         if (empty($this->importoptions['shortnametemplate'])) {
             $this->error('missingshortnamenotemplate', new lang_string('missingshortnamenotemplate', 'tool_uploadcourse'));
             return false;
         } else {
             if (!$this->can_only_create()) {
                 $this->error('cannotgenerateshortnameupdatemode', new lang_string('cannotgenerateshortnameupdatemode', 'tool_uploadcourse'));
                 return false;
             } else {
                 $newshortname = tool_uploadcourse_helper::generate_shortname($coursedata, $this->importoptions['shortnametemplate']);
                 if (is_null($newshortname)) {
                     $this->error('generatedshortnameinvalid', new lang_string('generatedshortnameinvalid', 'tool_uploadcourse'));
                     return false;
                 } else {
                     if ($this->exists($newshortname)) {
                         if ($mode === tool_uploadcourse_processor::MODE_CREATE_NEW) {
                             $this->error('generatedshortnamealreadyinuse', new lang_string('generatedshortnamealreadyinuse', 'tool_uploadcourse'));
                             return false;
                         }
                         $exists = true;
                     }
                 }
                 $this->status('courseshortnamegenerated', new lang_string('courseshortnamegenerated', 'tool_uploadcourse', $newshortname));
                 $this->shortname = $newshortname;
             }
         }
     }
     // If exists, but we only want to create courses, increment the shortname.
     if ($exists && $mode === tool_uploadcourse_processor::MODE_CREATE_ALL) {
         $original = $this->shortname;
         $this->shortname = tool_uploadcourse_helper::increment_shortname($this->shortname);
         $exists = false;
         if ($this->shortname != $original) {
             $this->status('courseshortnameincremented', new lang_string('courseshortnameincremented', 'tool_uploadcourse', array('from' => $original, 'to' => $this->shortname)));
             if (isset($coursedata['idnumber'])) {
                 $originalidn = $coursedata['idnumber'];
                 $coursedata['idnumber'] = tool_uploadcourse_helper::increment_idnumber($coursedata['idnumber']);
                 if ($originalidn != $coursedata['idnumber']) {
                     $this->status('courseidnumberincremented', new lang_string('courseidnumberincremented', 'tool_uploadcourse', array('from' => $originalidn, 'to' => $coursedata['idnumber'])));
                 }
             }
         }
     }
     // If the course does not exist, ensure that the ID number is not taken.
     if (!$exists && isset($coursedata['idnumber'])) {
         if ($DB->count_records_select('course', 'idnumber = :idn', array('idn' => $coursedata['idnumber'])) > 0) {
             $this->error('idnumberalreadyinuse', new lang_string('idnumberalreadyinuse', 'tool_uploadcourse'));
             return false;
         }
     }
     // Course start date.
     if (!empty($coursedata['startdate'])) {
         $coursedata['startdate'] = strtotime($coursedata['startdate']);
     }
     // Course end date.
     if (!empty($coursedata['enddate'])) {
         $coursedata['enddate'] = strtotime($coursedata['enddate']);
     }
     // Ultimate check mode vs. existence.
     switch ($mode) {
         case tool_uploadcourse_processor::MODE_CREATE_NEW:
         case tool_uploadcourse_processor::MODE_CREATE_ALL:
             if ($exists) {
                 $this->error('courseexistsanduploadnotallowed', new lang_string('courseexistsanduploadnotallowed', 'tool_uploadcourse'));
                 return false;
             }
             break;
         case tool_uploadcourse_processor::MODE_UPDATE_ONLY:
             if (!$exists) {
                 $this->error('coursedoesnotexistandcreatenotallowed', new lang_string('coursedoesnotexistandcreatenotallowed', 'tool_uploadcourse'));
                 return false;
             }
             // No break!
         // No break!
         case tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE:
             if ($exists) {
                 if ($updatemode === tool_uploadcourse_processor::UPDATE_NOTHING) {
                     $this->error('updatemodedoessettonothing', new lang_string('updatemodedoessettonothing', 'tool_uploadcourse'));
                     return false;
                 }
             }
             break;
         default:
             // O_o Huh?! This should really never happen here!
             $this->error('unknownimportmode', new lang_string('unknownimportmode', 'tool_uploadcourse'));
             return false;
     }
     // Get final data.
     if ($exists) {
         $missingonly = $updatemode === tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS;
         $coursedata = $this->get_final_update_data($coursedata, $usedefaults, $missingonly);
         // Make sure we are not trying to mess with the front page, though we should never get here!
         if ($coursedata['id'] == $SITE->id) {
             $this->error('cannotupdatefrontpage', new lang_string('cannotupdatefrontpage', 'tool_uploadcourse'));
             return false;
         }
         $this->do = self::DO_UPDATE;
     } else {
         $coursedata = $this->get_final_create_data($coursedata);
         $this->do = self::DO_CREATE;
     }
     // Validate course start and end dates.
     if ($exists) {
         // We also check existing start and end dates if we are updating an existing course.
         $existingdata = $DB->get_record('course', array('shortname' => $this->shortname));
         if (empty($coursedata['startdate'])) {
             $coursedata['startdate'] = $existingdata->startdate;
         }
         if (empty($coursedata['enddate'])) {
             $coursedata['enddate'] = $existingdata->enddate;
         }
     }
     if ($errorcode = course_validate_dates($coursedata)) {
         $this->error($errorcode, new lang_string($errorcode, 'error'));
         return false;
     }
     // Add role renaming.
     $errors = array();
     $rolenames = tool_uploadcourse_helper::get_role_names($this->rawdata, $errors);
     if (!empty($errors)) {
         foreach ($errors as $key => $message) {
             $this->error($key, $message);
         }
         return false;
     }
     foreach ($rolenames as $rolekey => $rolename) {
         $coursedata[$rolekey] = $rolename;
     }
     // Some validation.
     if (!empty($coursedata['format']) && !in_array($coursedata['format'], tool_uploadcourse_helper::get_course_formats())) {
         $this->error('invalidcourseformat', new lang_string('invalidcourseformat', 'tool_uploadcourse'));
         return false;
     }
     // Saving data.
     $this->data = $coursedata;
     $this->enrolmentdata = tool_uploadcourse_helper::get_enrolment_data($this->rawdata);
     if (isset($this->rawdata['tags']) && strval($this->rawdata['tags']) !== '') {
         $this->data['tags'] = preg_split('/\\s*,\\s*/', trim($this->rawdata['tags']), -1, PREG_SPLIT_NO_EMPTY);
     }
     // Restore data.
     // TODO Speed up things by not really extracting the backup just yet, but checking that
     // the backup file or shortname passed are valid. Extraction should happen in proceed().
     $this->restoredata = $this->get_restore_content_dir();
     if ($this->restoredata === false) {
         return false;
     }
     // We can only reset courses when allowed and we are updating the course.
     if ($this->importoptions['reset'] || $this->options['reset']) {
         if ($this->do !== self::DO_UPDATE) {
             $this->error('canonlyresetcourseinupdatemode', new lang_string('canonlyresetcourseinupdatemode', 'tool_uploadcourse'));
             return false;
         } else {
             if (!$this->can_reset()) {
                 $this->error('courseresetnotallowed', new lang_string('courseresetnotallowed', 'tool_uploadcourse'));
                 return false;
             }
         }
     }
     return true;
 }
Ejemplo n.º 4
0
 /**
  * Validation.
  *
  * @param array $data
  * @param array $files
  * @return array the errors that were found
  */
 function validation($data, $files)
 {
     global $DB;
     $errors = parent::validation($data, $files);
     // Add field validation check for duplicate shortname.
     if ($course = $DB->get_record('course', array('shortname' => $data['shortname']), '*', IGNORE_MULTIPLE)) {
         if (empty($data['id']) || $course->id != $data['id']) {
             $errors['shortname'] = get_string('shortnametaken', '', $course->fullname);
         }
     }
     // Add field validation check for duplicate idnumber.
     if (!empty($data['idnumber']) && (empty($data['id']) || $this->course->idnumber != $data['idnumber'])) {
         if ($course = $DB->get_record('course', array('idnumber' => $data['idnumber']), '*', IGNORE_MULTIPLE)) {
             if (empty($data['id']) || $course->id != $data['id']) {
                 $errors['idnumber'] = get_string('courseidnumbertaken', 'error', $course->fullname);
             }
         }
     }
     if ($errorcode = course_validate_dates($data)) {
         $errors['enddate'] = get_string($errorcode, 'error');
     }
     $errors = array_merge($errors, enrol_course_edit_validation($data, $this->context));
     $courseformat = course_get_format((object) array('format' => $data['format']));
     $formaterrors = $courseformat->edit_form_validation($data, $files, $errors);
     if (!empty($formaterrors) && is_array($formaterrors)) {
         $errors = array_merge($errors, $formaterrors);
     }
     return $errors;
 }
Ejemplo n.º 5
0
 /**
  * Validation.
  *
  * @param array $data
  * @param array $files
  * @return array the errors that were found
  */
 public function validation($data, $files)
 {
     global $DB;
     $course = get_course($data['id']);
     $errors = parent::validation($data, $files);
     // We check the values that would be used as start and end.
     if ($data['reset_start_date'] != 0) {
         $coursedata['startdate'] = $data['reset_start_date'];
     } else {
         $coursedata['startdate'] = $course->startdate;
     }
     if ($data['reset_end_date'] != 0) {
         // End date set by the user has preference.
         $coursedata['enddate'] = $data['reset_end_date'];
     } else {
         if ($data['reset_start_date'] > 0 && $course->enddate != 0) {
             // Otherwise, if the current course enddate is set, reset_course_userdata will add the start date time shift to it.
             $timeshift = $data['reset_start_date'] - usergetmidnight($course->startdate);
             $coursedata['enddate'] = $course->enddate + $timeshift;
         } else {
             $coursedata['enddate'] = $course->enddate;
         }
     }
     if ($errorcode = course_validate_dates($coursedata)) {
         $errors['reset_end_date'] = get_string($errorcode, 'error');
     }
     return $errors;
 }