function update_resource_type($ref, $type)
{
    sql_query("update resource set resource_type='{$type}' where ref='{$ref}'");
    # Clear data that is no longer needed (data/keywords set for other types).
    sql_query("delete from resource_data where resource='{$ref}' and resource_type_field not in (select ref from resource_type_field where resource_type='{$type}' or resource_type=999 or resource_type=0)");
    sql_query("delete from resource_keyword where resource='{$ref}' and resource_type_field>0 and resource_type_field not in (select ref from resource_type_field where resource_type='{$type}' or resource_type=999 or resource_type=0)");
    # Also index the resource type name, unless disabled
    global $index_resource_type;
    if ($index_resource_type) {
        $restypename = sql_value("select name value from resource_type where ref='" . escape_check($type) . "'", "");
        remove_all_keyword_mappings_for_field($ref, -2);
        add_keyword_mappings($ref, $restypename, -2);
    }
}
function save_resource_data($ref, $multi, $autosave_field = "")
{
    # Save all submitted data for resource $ref.
    # Also re-index all keywords from indexable fields.
    global $auto_order_checkbox, $userresourcedefaults, $multilingual_text_fields, $languages, $language, $user_resources_approved_email;
    hook("befsaveresourcedata", "", array($ref));
    # save resource defaults
    # (do this here so that user can override them if the fields are visible.)
    if ($autosave_field == "") {
        set_resource_defaults($ref);
    }
    # Loop through the field data and save (if necessary)
    $errors = array();
    $fields = get_resource_field_data($ref, $multi, !hook("customgetresourceperms"));
    $expiry_field_edited = false;
    $resource_data = get_resource_data($ref);
    # Load the configuration for the selected resource type. Allows for alternative notification addresses, etc.
    resource_type_config_override($resource_data["resource_type"]);
    for ($n = 0; $n < count($fields); $n++) {
        if (!(checkperm("F" . $fields[$n]["ref"]) || checkperm("F*") && !checkperm("F-" . $fields[$n]["ref"])) && ($autosave_field == "" || $autosave_field == $fields[$n]["ref"] || is_array($autosave_field) && in_array($fields[$n]["ref"], $autosave_field))) {
            if ($fields[$n]["type"] == 2) {
                # construct the value from the ticked boxes
                $val = ",";
                # Note: it seems wrong to start with a comma, but this ensures it is treated as a comma separated list by split_keywords(), so if just one item is selected it still does individual word adding, so 'South Asia' is split to 'South Asia','South','Asia'.
                $options = trim_array(explode(",", $fields[$n]["options"]));
                for ($m = 0; $m < count($options); $m++) {
                    $name = $fields[$n]["ref"] . "_" . md5($options[$m]);
                    if (getval($name, "") == "yes") {
                        if ($val != ",") {
                            $val .= ",";
                        }
                        $val .= $options[$m];
                    }
                }
            } elseif ($fields[$n]["type"] == 4 || $fields[$n]["type"] == 6 || $fields[$n]["type"] == 10) {
                # date type, construct the value from the date/time dropdowns
                $val = sprintf("%04d", getvalescaped("field_" . $fields[$n]["ref"] . "-y", ""));
                if ((int) $val <= 0) {
                    $val = "";
                } elseif (($field = getvalescaped("field_" . $fields[$n]["ref"] . "-m", "")) != "") {
                    $val .= "-" . $field;
                    if (($field = getvalescaped("field_" . $fields[$n]["ref"] . "-d", "")) != "") {
                        $val .= "-" . $field;
                        if (($field = getval("field_" . $fields[$n]["ref"] . "-h", "")) != "") {
                            $val .= " " . $field . ":";
                            if (($field = getvalescaped("field_" . $fields[$n]["ref"] . "-i", "")) != "") {
                                $val .= $field;
                            } else {
                                $val .= "00";
                            }
                        }
                    }
                }
            } elseif ($multilingual_text_fields && ($fields[$n]["type"] == 0 || $fields[$n]["type"] == 1 || $fields[$n]["type"] == 5)) {
                # Construct a multilingual string from the submitted translations
                $val = getvalescaped("field_" . $fields[$n]["ref"], "");
                $val = "~" . $language . ":" . $val;
                reset($languages);
                foreach ($languages as $langkey => $langname) {
                    if ($language != $langkey) {
                        $val .= "~" . $langkey . ":" . getvalescaped("multilingual_" . $n . "_" . $langkey, "");
                    }
                }
            } elseif ($fields[$n]["type"] == 3 || $fields[$n]["type"] == 12) {
                $val = getvalescaped("field_" . $fields[$n]["ref"], "");
                // if it doesn't already start with a comma, add one
                if (substr($val, 0, 1) != ',') {
                    $val = ',' . $val;
                }
            } else {
                # Set the value exactly as sent.
                $val = getvalescaped("field_" . $fields[$n]["ref"], "");
            }
            # Check for regular expression match
            if (trim(strlen($fields[$n]["regexp_filter"])) >= 1 && strlen($val) > 0) {
                if (preg_match("#^" . $fields[$n]["regexp_filter"] . "\$#", $val, $matches) <= 0) {
                    global $lang;
                    debug($lang["information-regexp_fail"] . ": -" . "reg exp: " . $fields[$n]["regexp_filter"] . ". Value passed: " . $val);
                    if (getval("autosave", "") != "") {
                        exit;
                    }
                    $errors[$fields[$n]["ref"]] = $lang["information-regexp_fail"] . " : " . $val;
                    continue;
                }
            }
            $modified_val = hook("modifiedsavedfieldvalue", '', array($fields, $n, $val));
            if (!empty($modified_val)) {
                $val = $modified_val;
            }
            $error = hook("additionalvalcheck", "all", array($fields, $fields[$n]));
            if ($error) {
                global $lang;
                if (getval("autosave", "") != "") {
                    exit($error);
                }
                $errors[$fields[$n]["ref"]] = $error;
                continue;
            }
            if (str_replace("\r\n", "\n", $fields[$n]["value"]) !== str_replace("\r\n", "\n", unescape($val))) {
                //$testvalue=$fields[$n]["value"];var_dump($testvalue);$val=unescape($val);var_dump($val);
                //echo "FIELD:".$fields[$n]["value"]."!==ORIG:".unescape($val);
                $oldval = $fields[$n]["value"];
                # This value is different from the value we have on record.
                # Write this edit to the log (including the diff) (unescaped is safe because the diff is processed later)
                resource_log($ref, 'e', $fields[$n]["ref"], "", $fields[$n]["value"], unescape($val));
                # Expiry field? Set that expiry date(s) have changed so the expiry notification flag will be reset later in this function.
                if ($fields[$n]["type"] == 6) {
                    $expiry_field_edited = true;
                }
                # If 'resource_column' is set, then we need to add this to a query to back-update
                # the related columns on the resource table
                $resource_column = $fields[$n]["resource_column"];
                # Purge existing data and keyword mappings, decrease keyword hitcounts.
                sql_query("delete from resource_data where resource='{$ref}' and resource_type_field='" . $fields[$n]["ref"] . "'");
                # Insert new data and keyword mappings, increase keyword hitcounts.
                sql_query("insert into resource_data(resource,resource_type_field,value) values('{$ref}','" . $fields[$n]["ref"] . "','" . escape_check($val) . "')");
                if ($fields[$n]["type"] == 3 && substr($oldval, 0, 1) != ',') {
                    # Prepend a comma when indexing dropdowns
                    $oldval = "," . $oldval;
                }
                if ($fields[$n]["keywords_index"] == 1) {
                    # Date field? These need indexing differently.
                    $is_date = $fields[$n]["type"] == 4 || $fields[$n]["type"] == 6;
                    $is_html = $fields[$n]["type"] == 8;
                    remove_keyword_mappings($ref, i18n_get_indexable($oldval), $fields[$n]["ref"], $fields[$n]["partial_index"], $is_date, '', '', $is_html);
                    add_keyword_mappings($ref, i18n_get_indexable($val), $fields[$n]["ref"], $fields[$n]["partial_index"], $is_date, '', '', $is_html);
                }
                # If this is a 'joined' field we need to add it to the resource column
                $joins = get_resource_table_joins();
                if (in_array($fields[$n]["ref"], $joins)) {
                    if (substr($val, 0, 1) == ",") {
                        $val = substr($val, 1);
                    }
                    sql_query("update resource set field" . $fields[$n]["ref"] . "='" . escape_check($val) . "' where ref='{$ref}'");
                }
                # Add any onchange code
                if ($fields[$n]["onchange_macro"] != "") {
                    eval($fields[$n]["onchange_macro"]);
                }
            }
            # Check required fields have been entered.
            $exemptfields = getvalescaped("exemptfields", "");
            $exemptfields = explode(",", $exemptfields);
            if ($fields[$n]["required"] == 1 && ($val == "" || $val == ",") && !in_array($fields[$n]["ref"], $exemptfields)) {
                global $lang;
                $errors[$fields[$n]["ref"]] = i18n_get_translated($fields[$n]["title"]) . ": " . $lang["requiredfield"];
            }
        }
    }
    //die();
    if ($autosave_field == "") {
        # Additional tasks when editing all fields (i.e. not autosaving)
        # Always index the resource ID as a keyword
        remove_keyword_mappings($ref, $ref, -1);
        add_keyword_mappings($ref, $ref, -1);
        # Also index the resource type name, unless disabled
        global $index_resource_type;
        if ($index_resource_type) {
            $restypename = sql_value("select name value from resource_type where ref in (select resource_type from resource where ref='" . escape_check($ref) . "')", "");
            remove_all_keyword_mappings_for_field($ref, -2);
            add_keyword_mappings($ref, $restypename, -2);
        }
        # Autocomplete any blank fields.
        autocomplete_blank_fields($ref);
        # Also save related resources field
        sql_query("delete from resource_related where resource='{$ref}' or related='{$ref}'");
        # remove existing related items
        $related = explode(",", getvalescaped("related", ""));
        # Make sure all submitted values are numeric
        $ok = array();
        for ($n = 0; $n < count($related); $n++) {
            if (is_numeric(trim($related[$n]))) {
                $ok[] = trim($related[$n]);
            }
        }
        if (count($ok) > 0) {
            sql_query("insert into resource_related(resource,related) values ({$ref}," . join("),(" . $ref . ",", $ok) . ")");
        }
    }
    # Expiry field(s) edited? Reset the notification flag so that warnings are sent again when the date is reached.
    $expirysql = "";
    if ($expiry_field_edited) {
        $expirysql = ",expiry_notification_sent=0";
    }
    if (!hook('forbidsavearchive', '', array($errors))) {
        # Also update archive status and access level
        $oldaccess = $resource_data['access'];
        $access = getvalescaped("access", $oldaccess, true);
        #$oldarchive=sql_value("select archive value from resource where ref='$ref'","");
        $oldarchive = $resource_data['archive'];
        $setarchivestate = getvalescaped("status", $oldarchive, true);
        if ($setarchivestate != $oldarchive && !checkperm("e" . $setarchivestate)) {
            $setarchivestate = $oldarchive;
        }
        if ($access != $oldaccess || $setarchivestate != $oldarchive) {
            sql_query("update resource set archive='" . $setarchivestate . "',access='" . $access . "' {$expirysql} where ref='{$ref}'");
            if ($setarchivestate != $oldarchive && $ref > 0) {
                resource_log($ref, "s", 0, "", $oldarchive, $setarchivestate);
            }
            if ($access != $oldaccess && $ref > 0) {
                resource_log($ref, "a", 0, "", $oldaccess, $access);
            }
            // Notify the resources team ($email_notify) if moving from pending submission -> review.
            if ($oldarchive == -2 && $setarchivestate == -1 && $ref > 0) {
                notify_user_contributed_submitted(array($ref));
            }
            if ($oldarchive == -1 && $setarchivestate == -2 && $ref > 0) {
                notify_user_contributed_unsubmitted(array($ref));
            }
            if ($user_resources_approved_email) {
                if (($oldarchive == -2 || $oldarchive == -1) && $ref > 0 && $setarchivestate == 0) {
                    notify_user_resources_approved(array($ref));
                }
            }
        }
    }
    # For access level 3 (custom) - also save custom permissions
    if (getvalescaped("access", 0) == 3) {
        save_resource_custom_access($ref);
    }
    # Update XML metadata dump file
    update_xml_metadump($ref);
    hook("aftersaveresourcedata");
    if (count($errors) == 0) {
        return true;
    } else {
        return $errors;
    }
}