/**
 * Increments idnumber - increments trailing number or adds it if not present.
 * Varifies that the new idnumber does not exist yet
 * @param string $idnumber
 * @return incremented idnumber which does not exist yet
 */
function cc_increment_idnumber($idnumber)
{
    global $DB, $CFG;
    if (!preg_match_all('/(.*?)([0-9]+)$/', $idnumber, $matches)) {
        $idnumber = $idnumber . '2';
    } else {
        $idnumber = $matches[1][0] . ($matches[2][0] + 1);
    }
    if ($DB->record_exists('course_categories', array('idnumber' => $idnumber))) {
        return cc_increment_idnumber($idnumber);
    } else {
        return $idnumber;
    }
}
     // we require name too - we might use template for it though
     if (empty($coursecategory->name) and !empty($formdata->ccname)) {
         $coursecategory->name = cc_process_template($formdata->ccname, $coursecategory);
         $upt->track('name', s($coursecategory->name));
     }
 }
 // find category
 if ($existingcategory = $DB->get_record('course_categories', array('name' => trim($coursecategory->name), 'parent' => $coursecategory->parent))) {
     $upt->track('id', $existingcategory->id, 'normal', false);
 }
 // find out in name incrementing required
 if ($existingcategory and $optype == CC_COURSE_ADDINC) {
     $coursecategory->name = cc_increment_name($coursecategory->name);
     if (!empty($coursecategory->idnumber)) {
         $oldidnumber = $coursecategory->idnumber;
         $coursecategory->idnumber = cc_increment_idnumber($coursecategory->idnumber);
         if ($coursecategory->idnumber !== $oldidnumber) {
             $upt->track('idnumber', s($oldidnumber) . '-->' . s($coursecategory->idnumber), 'info');
         }
     }
     $existingcategory = false;
 }
 // check duplicate idnumber
 if (!$existingcategory and isset($coursecategory->idnumber)) {
     if ($DB->record_exists('course_categories', array('idnumber' => $coursecategory->idnumber))) {
         $upt->track('status', get_string('idnumbernotunique', 'tool_uploadcoursecategory'), 'error');
         $upt->track('idnumber', $errorstr, 'error');
         $error = true;
     }
 }
 $categories[] = $coursecategory->name;
 /**
  * Validates and prepares the data.
  *
  * @return bool false is any error occured.
  */
 public function prepare()
 {
     global $DB;
     $this->prepared = true;
     // Checking mandatory fields.
     foreach (self::$mandatoryfields as $key => $field) {
         if (!isset($this->rawdata[$field])) {
             $this->error('missingfield', new lang_string('missingfield', 'error', $field));
             return false;
         }
     }
     // Validate idnumber field.
     if (isset($this->rawdata['idnumber']) && !is_numeric($this->rawdata['idnumber'])) {
         $this->error('idnumbernotanumber', new lang_string('idnumbernotanumber', 'tool_uploadcoursecategory'));
         return false;
     }
     // Standardise name
     if (isset($this->importoptions['standardise'])) {
         $this->name = clean_param($this->name, PARAM_MULTILANG);
     }
     // Validate parent hierarchy.
     $this->parentid = $this->prepare_parent();
     if ($this->parentid == -1) {
         $this->error('missingcategoryparent', new lang_string('missingcategoryparent', 'tool_uploadcoursecategory'));
         return false;
     }
     $this->existing = $this->exists();
     // Can we delete the category?
     if (!empty($this->options['deleted'])) {
         if (empty($this->existing)) {
             $this->error('coursecategorynotdeletedmissing', new lang_string('coursecategorynotdeletedmissing', 'tool_uploadcoursecategory'));
             return false;
         } else {
             if (!$this->can_delete()) {
                 $this->error('coursecategorynotdeletedoff', new lang_string('coursecategorynotdeletedoff', 'tool_uploadcoursecategory'));
                 return false;
             }
         }
         $this->do = self::DO_DELETE;
         // We only need the name and parent id for category deletion.
         return true;
     }
     // Can we create/update the course under those conditions?
     if ($this->existing) {
         if ($this->mode === tool_uploadcoursecategory_processor::MODE_CREATE_NEW) {
             $this->error('coursecategoryupdateoff', new lang_string('coursecategorynotupdatedoff', 'tool_uploadcoursecategory'));
             return false;
         }
     } else {
         // If I cannot create the course, or I'm in update-only mode and I'm
         // not renaming
         if (!$this->can_create() && $this->mode === tool_uploadcoursecategory_processor::MODE_UPDATE_ONLY && !isset($this->rawdata['oldname'])) {
             $this->error('coursecategorynotcreatedoff', new lang_string('coursecategorynotcreatedoff', 'tool_uploadcoursecategory'));
             return false;
         }
     }
     // Preparing final category data.
     $finaldata = array();
     foreach ($this->rawdata as $field => $value) {
         if (!in_array($field, self::$validfields)) {
             continue;
         }
         $finaldata[$field] = $value;
     }
     $finaldata['name'] = $this->name;
     // Can the category be renamed?
     if (!empty($finaldata['oldname'])) {
         if ($this->existing) {
             $this->error('coursecategorynotrenamedexists', new lang_string('coursecategorynotrenamedexists', 'tool_uploadcoursecategory'));
             return false;
         }
         $categories = explode('/', $finaldata['oldname']);
         $oldname = array_pop($categories);
         $oldname = trim($oldname);
         if (isset($this->importoptions['standardise'])) {
             $oldname = clean_param($oldname, PARAM_MULTILANG);
         }
         $oldparentid = $this->prepare_parent($categories, 0);
         $this->existing = $this->exists($oldname, $oldparentid);
         if ($oldparentid === -1) {
             $this->error('oldcategoryhierarchydoesnotexist', new lang_string('coldcategoryhierarchydoesnotexist', 'tool_uploadcoursecategory'));
             return false;
         } else {
             if (!$this->can_update()) {
                 $this->error('coursecastegorynotupdatedoff', new lang_string('coursecategorynotupdatedoff', 'tool_uploadcoursecategory'));
                 return false;
             } else {
                 if (!$this->existing) {
                     $this->error('coursecategorynotrenamedmissing', new lang_string('coursecategorynotrenamedmissing', 'tool_uploadcoursecategory'));
                     return false;
                 } else {
                     if (!$this->can_rename()) {
                         $this->error('coursecategorynotrenamedoff', new lang_string('coursecategorynotrenamedoff', 'tool_uploadcoursecategory'));
                         return false;
                     } else {
                         if (isset($this->rawdata['idnumber'])) {
                             // If category id belongs to another category
                             if ($this->existing->idnumber !== $finaldata['idnumber'] && $DB->record_exists('course_categories', array('idnumber' => $finaldata['idnumber']))) {
                                 $this->error('idnumberalexists', new lang_string('idnumberexists', 'tool_uploadcoursecategory'));
                                 return false;
                             }
                         }
                     }
                 }
             }
         }
         // All the needed operations for renaming are done.
         $this->finaldata = $this->get_final_update_data($finaldata, $this->existing);
         $this->do = self::DO_UPDATE;
         $this->set_status('coursecategoryrenamed', new lang_string('coursecategoryrenamed', 'tool_uploadcoursecategory', array('from' => $oldname, 'to' => $finaldata['name'])));
         return true;
     }
     // If exists, but we only want to create categories, increment the name.
     if ($this->existing && $this->mode === tool_uploadcoursecategory_processor::MODE_CREATE_ALL) {
         $original = $this->name;
         $this->name = cc_increment_name($this->name);
         // We are creating a new course category
         $this->existing = null;
         if ($this->name !== $original) {
             $this->set_status('coursecategoryrenamed', new lang_string('coursecategoryrenamed', 'tool_uploadcoursecategory', array('from' => $original, 'to' => $this->name)));
             if (isset($finaldata['idnumber'])) {
                 $originalidn = $finaldata['idnumber'];
                 $finaldata['idnumber'] = cc_increment_idnumber($finaldata['idnumber']);
             }
         }
     }
     // Check if idnumber is already taken
     if (!$this->existing && isset($finaldata['idnumber']) && $DB->record_exists('course_categories', array('idnumber' => $finaldata['idnumber']))) {
         $this->error('idnumberexists', new lang_string('idnumberexists', 'tool_uploadcoursecategory'));
         return false;
     }
     // Ultimate check mode vs. existence.
     switch ($this->mode) {
         case tool_uploadcoursecategory_processor::MODE_CREATE_NEW:
         case tool_uploadcoursecategory_processor::MODE_CREATE_ALL:
             if ($this->existing) {
                 $this->error('coursecategorynotupdatedoff', new lang_string('coursecategorynotupdatedoff', 'tool_uploadcoursecategory'));
                 return false;
             }
             break;
         case tool_uploadcoursecategory_processor::MODE_UPDATE_ONLY:
             if (!$this->existing) {
                 $this->error('coursecategorynotcreatedoff', new lang_string('coursecategorynotcreatedoff', 'tool_uploadcoursecategory'));
                 return false;
             }
             // No break!
         // No break!
         case tool_uploadcoursecategory_processor::MODE_CREATE_OR_UPDATE:
             if ($this->existing) {
                 if ($this->updatemode === tool_uploadcoursecategory_processor::UPDATE_NOTHING) {
                     $this->error('coursecategorynotupdatednothing', new lang_string('coursecategorynotupdatednothing', 'tool_uploadcoursecategory'));
                     return false;
                 }
             }
             break;
         default:
             // O_o Huh?! This should really never happen here!
             $this->error('unknownuploadmode', new lang_string('unknownuploadmode', 'tool_uploadcoursecategory'));
             return false;
     }
     // Get final data.
     if ($this->existing) {
         $missingonly = $updatemode === tool_uploadcoursecategory_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAULTS;
         $finaldata = $this->get_final_update_data($finaldata, $this->existing, $this->defaults, $missingonly);
         // Make sure we are not trying to mess with the front page, though we should never get here!
         if ($finaldata['id'] == $SITE->id) {
             $this->error('cannotupdatefrontpage', new lang_string('cannotupdatefrontpage', 'tool_uploadcoursecategory'));
             return false;
         }
         $this->do = self::DO_UPDATE;
     } else {
         $finaldata = $this->get_final_create_data($finaldata);
         $this->do = self::DO_CREATE;
     }
     // Saving data.
     $this->finaldata = $finaldata;
     return true;
 }