public function resort_courses($field, $cleanup = true) {
        global $DB;
        $desc = false;
        if (substr($field, -4) === "desc") {
            $desc = true;
            $field = substr($field, 0, -4);  // Remove "desc" from field name.
        }
        if ($field !== 'fullname' && $field !== 'shortname' && $field !== 'idnumber' && $field !== 'timecreated') {
            // This is ultra important as we use $field in an SQL statement below this.
            throw new coding_exception('Invalid field requested');
        }
        $ctxfields = context_helper::get_preload_record_columns_sql('ctx');
        $sql = "SELECT c.id, c.sortorder, c.{$field}, $ctxfields
                  FROM {course} c
             LEFT JOIN {context} ctx ON ctx.instanceid = c.id
                 WHERE ctx.contextlevel = :ctxlevel AND
                       c.category = :categoryid";
        $params = array(
            'ctxlevel' => CONTEXT_COURSE,
            'categoryid' => $this->id
        );
        $courses = $DB->get_records_sql($sql, $params);
        if (count($courses) > 0) {
            foreach ($courses as $courseid => $course) {
                context_helper::preload_from_record($course);
                if ($field === 'idnumber') {
                    $course->sortby = $course->idnumber;
                } else {
                    // It'll require formatting.
                    $options = array(
                        'context' => context_course::instance($course->id)
                    );
                    // We format the string first so that it appears as the user would see it.
                    // This ensures the sorting makes sense to them. However it won't necessarily make
                    // sense to everyone if things like multilang filters are enabled.
                    // We then strip any tags as we don't want things such as image tags skewing the
                    // sort results.
                    $course->sortby = strip_tags(format_string($course->$field, true, $options));
                }
                // We set it back here rather than using references as there is a bug with using
                // references in a foreach before passing as an arg by reference.
                $courses[$courseid] = $course;
            }
            // Sort the courses.
            core_collator::asort_objects_by_property($courses, 'sortby', core_collator::SORT_NATURAL);
            if (!empty($desc)) {
                $courses = array_reverse($courses);
            }
            $i = 1;
            foreach ($courses as $course) {
                $DB->set_field('course', 'sortorder', $this->sortorder + $i, array('id' => $course->id));
                $i++;
            }
            if ($cleanup) {
                // This should not be needed but we do it just to be safe.
                fix_course_sortorder();
                cache_helper::purge_by_event('changesincourse');
            }
        }
        return true;
    }