<?PHP
#
#   FILE:  EditResourceComplete.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2011-2013 Edward Almasy and Internet Scout Project
#   http://scout.wisc.edu/
#

PageTitle("Resource Editing Complete");

if (!CheckAuthorization(PRIV_RESOURCEADMIN,
        PRIV_MYRESOURCEADMIN, PRIV_RELEASEADMIN)) {  return;  }

# ----- CONFIGURATION  -------------------------------------------------------

# ----- EXPORTED FUNCTIONS ---------------------------------------------------
# (functions intended for use in corresponding HTML file)

# ----- LOCAL FUNCTIONS ------------------------------------------------------
# (functions intended for use only within this file)

# error codes  (NOTE:  Must match codes in SPT--EditResourceCommon.html!!!)
define("ERR_FILEUPLOADERROR", 1);
define("ERR_ZEROLENGTH", 2);
define("ERR_IMAGEUPLOADERROR", 3);
define("ERR_UNSUPPORTEDIMAGEFORMAT", 4);
define("ERR_UNKNOWNIMAGETYPE", 5);
define("ERR_REQUIREDFIELDEMPTY", 6);
define("ERR_POSTEMPTY", 7);
define("ERR_IMAGESTORE", 8);
define("ERR_TEMPSTORE",  9);
define("ERR_FILESTORE", 10);

# return back to editing page with error info
function ReturnWithErrors($Resource, $Fields, $Error, $ErrOne = NULL, $ErrTwo = NULL)
{
    global $AF;

    if (is_array($Fields))
    {
        $FieldName = "Required Fields";
        $FieldInfo = "";
        foreach ($Fields as $Field)
        {
            $FieldInfo .= (strlen($FieldInfo) ? "-" : "").$Field->Id();
        }
    }
    else
    {
        $FieldName = $Fields->Name();
        $FieldInfo = $Fields->Id();
    }

    $AF->SetJumpToPage("EditResource&ID=".$Resource->Id()
                       ."&ER=".$Error."&EF=".$FieldInfo
                       .($ErrOne ? "&E1=".urlencode($ErrOne) : "")
                       .($ErrTwo ? "&E2=".urlencode($ErrTwo) : ""));
}

# update search and recommender system DBs (if dynamic updates enabled)
function UpdateSearchAndRecommender($Resource)
{
    if (!$Resource->IsTempResource())
    {
        $SearchEngine = new SPTSearchEngine();
        $SearchEngine->QueueUpdateForItem(
            $Resource->Id(),
            $GLOBALS["SysConfig"]->SearchEngineUpdatePriority());

        $Recommender = new SPTRecommender();
        $Recommender->QueueUpdateForItem(
            $Resource->Id(),
            $GLOBALS["SysConfig"]->RecommenderEngineUpdatePriority());

        $RFactory = new ResourceFactory();
        $RFactory->QueueResourceCountUpdate();
    }
}

# save values from editing form
# (returns array of any unfilled required fields)
# NOTE: Assumes that all form vars have been set appropriately
# before being called. Single-value fields are checked for existence
# with isset()'s, but because of how HTML forms work, multi-value fields
# cannot be.  If this function is called when coming from a page that
# didn't display a form, values in multi-select fields will be
# squashed.
function UpdateResource($Resource, $User)
{
    global $AF;

    # for each metadata field
    $Schema = new MetadataSchema($Resource->SchemaId());
    $Fields = $Schema->GetFields(NULL, MetadataSchema::MDFORDER_EDITING);
    $EmptyFields = array();
    $RecordChanged = FALSE;
    foreach ($Fields as $Field)
    {
        # if user has permission to edit field
        if ($Resource->UserCanEditField($User, $Field))
        {
            $OldValue = $Resource->Get($Field);
            switch ($Field->Type())
            {
                case MetadataSchema::MDFTYPE_TEXT:
                case MetadataSchema::MDFTYPE_NUMBER:
                case MetadataSchema::MDFTYPE_DATE:
                case MetadataSchema::MDFTYPE_TIMESTAMP:
                case MetadataSchema::MDFTYPE_PARAGRAPH:
                case MetadataSchema::MDFTYPE_FLAG:
                case MetadataSchema::MDFTYPE_URL:
                    # if we have a value from the form for this field
                    # (check necessary because user may push Save button
                    #       before form has finished loading)
                    if (isset($_POST["F_".$Field->DBFieldName()]))
                    {
                        # run value through any hooked filters
                        $NewValue = trim($_POST["F_".$Field->DBFieldName()]);
                        $SignalResult = $AF->SignalEvent(
                                "EVENT_POST_FIELD_EDIT_FILTER", array(
                                       "Field" => $Field,
                                       "Resource" => $Resource,
                                       "Value" => $NewValue));
                        $NewValue = $SignalResult["Value"];

                        # update release date if release flag was toggled to true
                        #       or if the release flag was true and the
                        #       Date of Record Release was NULL
                        $NewValue = StripXSSThreats($NewValue);
                        if ($Field->Name()=="Release Flag" &&
                            ((!$Resource->Get("Release Flag") && $NewValue == "1") ||
                             ($NewValue == "1" && is_null($Resource->Get("Date Of Record Release")))))
                        {
                            $Resource->Set("Date Of Record Release", date("Y-m-d H:i:s"));
                        }

                        # filter date field values for validity
                        if ($Field->Type() & (MetadataSchema::MDFTYPE_DATE
                                |MetadataSchema::MDFTYPE_TIMESTAMP))
                        {
                            $TestDate = new Date($NewValue);
                            if ($TestDate->Precision() == 0) {  $NewValue = "";  }
                        }

                        # filter url values for URI
                        if ($Field->Type() == MetadataSchema::MDFTYPE_URL
                            && strlen($NewValue)
                            && !preg_match('/^[a-zA-Z]+:\/\//', $NewValue))
                        {
                            $NewValue = "http://".$NewValue;
                        }

                        # filter HTML tags out of text values if appropriate
                        if ($Field->Type() & (MetadataSchema::MDFTYPE_TEXT
                                |MetadataSchema::MDFTYPE_PARAGRAPH))
                        {
                            if (!$Field->AllowHTML())
                            {
                                $NewValue = strip_tags($NewValue);
                            }
                        }

                        # if value was supplied or field is not required
                        if (strlen($NewValue) || $Field->Optional())
                        {
                            # save field
                            $Resource->Set($Field, $NewValue);
                        }
                        else
                        {
                            # add field to error list
                            $EmptyFields[] = $Field;
                        }
                    }
                    break;

                case MetadataSchema::MDFTYPE_POINT:
                    # if there are no values set
                    if (!isset($_POST["F_".$Field->DBFieldName()."X"])
                        || !isset($_POST["F_".$Field->DBFieldName()."Y"]))
                    {
                        # if the field isn't optional, add it to the error list
                        if (!$Field->Optional())
                        {
                            $EmptyFields[] = $Field;
                        }

                        # go to the next field
                        continue;
                    }

                    # run value through any hooked filters
                    $NewValue = array(
                            "X" => $_POST["F_".$Field->DBFieldName()."X"],
                            "Y" => $_POST["F_".$Field->DBFIeldName()."Y"]);
                    $SignalResult = $AF->SignalEvent(
                            "EVENT_POST_FIELD_EDIT_FILTER", array(
                                   "Field" => $Field,
                                   "Resource" => $Resource,
                                   "Value" => $NewValue));
                    $NewValue = $SignalResult["Value"];

                    # if value looks valid
                    if (is_numeric($NewValue["X"])
                        && is_numeric($NewValue["Y"]))
                    {
                        # save new value
                        $Resource->Set($Field, $NewValue);
                    }

                    # the field is optional and the values are blank
                    else if ($Field->Optional()
                        && !strlen(trim($NewValue["X"]))
                        && !strlen(trim($NewValue["Y"])))
                    {
                        # save blank value
                        $Resource->Set($Field, array("X" => "", "Y" => ""));
                    }

                    # empty fields and field is required
                    else if (!$Field->Optional())
                    {
                        # flag field as empty
                        $EmptyFields[] = $Field;
                    }
                    break;

                case MetadataSchema::MDFTYPE_TREE:
                case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
                    # while there are form values for this field
                    $ValueCount = $Field->GetCountOfPossibleValues();
                    $InterfaceToggleThreshold = 250;
                    $Factory = $Field->GetFactory();
                    $ValuesToSet = array();
                    $InputValues = array();

                    # old way it was being set
                    $BaseFieldName = "D_".$Field->DBFieldName()."_";
                    $FieldIndex = 1;

                    # set values the old way
                    if (isset($_POST[$BaseFieldName.$FieldIndex]))
                    {
                        while (isset($_POST[$BaseFieldName.$FieldIndex]))
                        {
                            # retrieve value from form field
                            $InputValues[] = $_POST[$BaseFieldName.$FieldIndex];

                            # move to the next form value
                            $FieldIndex++;
                        }
                    }

                    # set values the new way
                    else if (isset($_POST["F_".$Field->DBFieldName()]))
                    {
                        $InputValues = $_POST["F_".$Field->DBFieldName()];
                    }

                    foreach ($InputValues as $Value)
                    {
                        # If we have a non-empty value
                        if (strlen($Value))
                        {
                            # Check to see if it was a name, and if so
                            # convert it to an index.  Otherwise,
                            # it was already an index and we should use it
                            # directly.
                            $Item = $Factory->GetItemByName($Value);
                            if ($Item)
                            {
                                $Value = $Item->Id();
                            }

                            # it looks like it was being wrongly assumed that
                            # this would always be a number, but when there's
                            # an error, it won't find an item and display SQL
                            # errors later on. So, if the value isn't numeric,
                            # refuse to work with it
                            else if (!is_numeric($Value))
                            {
                                $Value = -1;
                            }

                            else
                            {
                                $Value = intval($Value);
                            }
                        }
                        else
                        {
                            $Value = -1;
                        }

                        # if form value appears valid
                        if ($Value >= 0)
                        {
                            # add value to list of those to be set
                            # (set method expects IDs to appear as indexes)
                            $ValuesToSet[$Value] = 1;
                        }
                    }

                    # if value found to set or field is not required
                    if (count($ValuesToSet) || $Field->Optional())
                    {
                        $OldKeys = array_keys($OldValue);
                        $NewKeys = array_keys($ValuesToSet);

                        sort($OldKeys);
                        sort($NewKeys);

                        if ($OldKeys != $NewKeys)
                        {
                            # clear any existing values for this field
                            $Resource->ClearByField($Field);

                            # if values found to set
                            if (count($ValuesToSet))
                            {
                                # set values in resource
                                $Resource->Set($Field, $ValuesToSet);
                            }
                        }
                    }
                    else
                    {
                        # add field to error list
                        $EmptyFields[] = $Field;
                    }
                    break;

                case MetadataSchema::MDFTYPE_OPTION:
                    # if field allows multiple values
                    $ValuesToSet = array();
                    if ($Field->AllowMultiple())
                    {
                        # retrieve possible values for this field
                        $PossibleValues = $Field->GetPossibleValues();

                        # newer way to get the values
                        if (isset($_POST["F_".$Field->DBFieldName()]))
                        {
                            $GivenValues = $_POST["F_".$Field->DBFieldName()];

                            # for each possible value
                            foreach ($PossibleValues as $ValueId => $ValueName)
                            {
                                # if form field is set for value
                                if (in_array($ValueId, $GivenValues))
                                {
                                    # add value to list of those to be set
                                    $ValuesToSet[$ValueId] = 1;
                                }
                            }
                        }

                        # old way to get the values
                        else
                        {
                            # for each possible value
                            foreach ($PossibleValues as $ValueId => $ValueName)
                            {
                                # if form field is set for value
                                if (isset($_POST["D_".$Field->DBFieldName()."_".$ValueId]))
                                {
                                    # add value to list of those to be set
                                    $ValuesToSet[$ValueId] = 1;
                                }
                            }
                        }
                    }
                    else
                    {
                        # retrieve value for this field (if available)
                        if (isset($_POST["F_".$Field->DBFieldName()]))
                        {
                            $ValuesToSet[$_POST["F_".$Field->DBFieldName()]] = 1;
                        }
                    }

                    # if value found to set or field is not required
                    if (count($ValuesToSet) || $Field->Optional())
                    {
                        $OldKeys = array_keys($OldValue);
                        $NewKeys = array_keys($ValuesToSet);

                        sort($OldKeys);
                        sort($NewKeys);

                        if ($OldKeys != $NewKeys)
                        {
                            # clear any existing values for this field
                            $Resource->ClearByField($Field);

                            # if values found to set
                            if (count($ValuesToSet))
                            {
                                # set values in resource
                                $Resource->Set($Field, $ValuesToSet);
                            }
                        }
                    }
                    else
                    {
                        # add field to error list
                        $EmptyFields[] = $Field;
                    }
                    break;

                case MetadataSchema::MDFTYPE_USER:
                    $NewValue = trim(GetArrayValue(
                        $_POST,
                        "F_".$Field->DBFieldName()));

                    if (strlen($NewValue))
                    {
                        $SignalResult = $AF->SignalEvent(
                                "EVENT_POST_FIELD_EDIT_FILTER", array(
                                       "Field" => $Field,
                                       "Resource" => $Resource,
                                       "Value" => $NewValue));

                        $NewValue = $SignalResult["Value"];
                        $Resource->Set($Field, $NewValue);
                    }

                    # allow the field to be unset if it's optional
                    else if ($Field->Optional())
                    {
                        $SignalResult = $AF->SignalEvent(
                                "EVENT_POST_FIELD_EDIT_FILTER", array(
                                       "Field" => $Field,
                                       "Resource" => $Resource,
                                       "Value" => $NewValue));

                        $NewValue = $SignalResult["Value"];
                        $Resource->Set($Field, $NewValue);
                    }

                    break;

                case MetadataSchema::MDFTYPE_REFERENCE:
                    # get the new value from the submitted form data
                    $NewValue = GetArrayValue(
                        $_POST,
                        "F_".$Field->DBFieldName(),
                        array());

                    foreach ($NewValue as $Key => $ReferenceId)
                    {
                        # remove any blank values
                        if (strlen(trim($ReferenceId)) < 1)
                        {
                            unset($NewValue[$Key]);
                        }

                        # remove any values that don't look right
                        if (!is_numeric($ReferenceId))
                        {
                            unset($NewValue[$Key]);
                        }
                    }

                    # set the new value
                    $Resource->Set($Field, $NewValue);
                    break;

                case MetadataSchema::MDFTYPE_IMAGE:
                    # for each image description
                    $Images = $Resource->Get($Field, TRUE);
                    foreach ($Images as $ImageId => $Image)
                    {
                        # if description has changed
                        $NewValue = GetArrayValue($_POST, "ImageAlt_".$ImageId);
                        if (!is_null($NewValue) && $NewValue != $Image->AltText())
                        {
                            # set new description
                            $Image->AltText($NewValue);

                            # set flag indicating record has changed
                            $RecordChanged = TRUE;
                        }
                    }
                    break;

                case MetadataSchema::MDFTYPE_FILE:
                    # (handled via special upload mechanisms)
                    break;

                default:
                    break;
            }
            # If anything changed, set the update flag.
            $RecordChanged |= ($OldValue
                               != $Resource->Get($Field));
        }
    }


    # If the record was changed, modify the appropriate timestamp fields
    if ($RecordChanged)
    {
        $TimestampFields = $Schema->GetFields(
            MetadataSchema::MDFTYPE_TIMESTAMP);
        foreach ($TimestampFields as $Field)
        {
            if ($Field->UpdateMethod() ==
                MetadataField::UPDATEMETHOD_ONRECORDCHANGE)
            {
                $Resource->Set($Field, "now");
            }
        }

        # update the last modified by ID field only if using the default schema
        if ($Schema->Id() == MetadataSchema::SCHEMAID_DEFAULT)
        {
            $Resource->Set("Last Modified By Id", $User);
        }

        # update search and recommender DBs if configured to do so
        UpdateSearchAndRecommender($Resource);

        # signal the modified event if the resource isn't a temp one
        if (!$Resource->IsTempResource())
        {
            $AF->SignalEvent("EVENT_RESOURCE_MODIFY", array("Resource" => $Resource));
        }
    }

    # return list of any empty required fields to caller
    return $EmptyFields;
}

# process File upload requests
function UploadFiles($Resource, $User)
{
    global $AF;

    # check to make sure that tmp is okay
    if ( !(is_dir("tmp") && is_writeable("tmp")) )
    {
        ReturnWithErrors($Resource, array(), ERR_TEMPSTORE);
    }
    # check to make sure that file storage directory is okay
    elseif (!is_dir(File::GetStorageDirectory())
            || !is_writeable(File::GetStorageDirectory()))
    {
        ReturnWithErrors($Resource, array(), ERR_FILESTORE);
    }
    else
    {
        # for each metadata field that might have an uploaded file
        $Schema = new MetadataSchema($Resource->SchemaId());
        $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_FILE);
        foreach ($Fields as $Field)
        {
            # if field is modifiable by specified user
            #       and we have an uploaded file for this field
            if ($Resource->UserCanEditField($User, $Field)
                && isset($_FILES[$Field->DBFieldName()]["tmp_name"])
                && is_uploaded_file($_FILES[$Field->DBFieldName()]["tmp_name"]))
            {
                # save uploaded file
                $TmpFileName = $_FILES[$Field->DBFieldName()]["tmp_name"];
                $NewFile = new File($TmpFileName, $Resource->Id(), $Field->Id(),
                                    $_FILES[$Field->DBFieldName()]["name"]);

                # if file save went fine
                if ($NewFile->Status() == File::FILESTAT_OK)
                {
                    $AF->SignalEvent(
                        "EVENT_RESOURCE_FILE_ADD",
                        array(
                            "Field" => $Field,
                            "Resource" => $Resource,
                            "File" => $NewFile));
                }

                else
                {
                    # set error message and error out
                    switch ($NewFile->Status())
                    {
                    case File::FILESTAT_ZEROLENGTH:
                        $Error = ERR_ZEROLENGTH;
                        break;

                    default:
                        $Error = ERR_FILEUPLOADERROR;
                        break;
                    }
                    $ErrParamOne = $_FILES[$Field->DBFieldName()]['name'];
                    $ErrParamTwo = $NewFile->Status();
                    ReturnWithErrors($Resource, $Field, $Error, $ErrParamOne, $ErrParamTwo);
                }

                # remove temp file
                unlink($TmpFileName);
            }
        }
    }
}

# process image upload requests
function UploadImages($Resource, $User)
{
    # Check to make sure that tmp is okay
    if ( !(is_dir("tmp") && is_writeable("tmp")) )
    {
        ReturnWithErrors($Resource, array(), ERR_TEMPSTORE);
    }
    # check to make sure image storage directories are okay
    elseif ($ErrorMsgs = SPTImage::CheckDirectories())
    {
        $ImagestoreErrors = "" ;

        foreach( $ErrorMsgs as $Message )
        {
            $ImagestoreErrors .= "<br>".$Message;
        }

        ReturnWithErrors($Resource, array(), ERR_IMAGESTORE,
                         $ImagestoreErrors);
    }
    else
    {
        # for each metadata field that might have an uploaded image
        $Schema = new MetadataSchema($Resource->SchemaId());
        $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_IMAGE);
        foreach ($Fields as $Field)
        {
            # if field is modifiable by specified user
            #       and we have an uploaded file for this field
            if ($Resource->UserCanEditField($User, $Field)
                && isset($_FILES[$Field->DBFieldName()]["tmp_name"])
                && is_uploaded_file($_FILES[$Field->DBFieldName()]["tmp_name"]))
            {
                # create temp copy of file with correct name
                $TempFile = "tmp/".$_FILES[$Field->DBFieldName()]['name'];
                copy($_FILES[$Field->DBFieldName()]["tmp_name"], $TempFile);

                # create new Image object from uploaded file
                $Image = new SPTImage($TempFile,
                                      $Field->MaxWidth(), $Field->MaxHeight(),
                                      $Field->MaxPreviewWidth(), $Field->MaxPreviewHeight(),
                                      $Field->MaxThumbnailWidth(), $Field->MaxThumbnailHeight());

                # if file save failed
                if ($Image->Status() != AI_OKAY)
                {
                    # set error message and error out
                    switch ($Image->Status())
                    {
                    case AI_UNKNOWNTYPE:
                    case AI_UNSUPPORTEDFORMAT:
                        $Error = ($Image->Status() == AI_UNSUPPORTEDFORMAT)
                            ? ERR_UNSUPPORTEDIMAGEFORMAT : ERR_UNKNOWNIMAGETYPE;
                        $ErrParamOne = $_FILES[$Field->DBFieldName()]['name'];
                        ReturnWithErrors($Resource, $Field, $Error, $ErrParamOne);
                        break;

                    default:
                        $Error = ERR_IMAGEUPLOADERROR;
                        $ErrParamOne = $_FILES[$Field->DBFieldName()]['name'];
                        $ErrParamTwo = $Image->Status();
                        ReturnWithErrors($Resource, $Field, $Error,
                                         $ErrParamOne, $ErrParamTwo);
                        break;
                    }
                }
                else
                {
                    # attach image to resource
                    $Resource->Set($Field, $Image->Id());

                    # set the image's alternate text
                    $AltText = GetArrayValue($_POST, "ImageAlt_".$Field->DBFieldName());
                    $Image->AltText($AltText);
                }
            }
        }
    }
}


# ----- MAIN -----------------------------------------------------------------
# PrintForDebug("_POST", $_POST);
# exit(1);

# set flags to defaults
$G_ResourceDeleted = FALSE;
$G_AddingCancelled = FALSE;
$G_EditingCancelled = FALSE;
$G_DeletionCancelled = FALSE;
$G_DeleteRequested = FALSE;
$G_FieldsEdited = FALSE;

# retrieve resource being edited
if (isset($_GET["ID"]))
{
    $G_Resource = new Resource(intval($_GET["ID"]));
}

# if we could not find resource with supplied ID
$Schema = new MetadataSchema($G_Resource->SchemaId());
if (!isset($G_Resource) || !is_object($G_Resource) || ($G_Resource->Status() != 1))
{
    $AF->SetJumpToPage("EditResource".
                       (isset($_GET["ID"])?"&ID=".intval($_GET["ID"]):""));
}
else
{
    if( count($_POST)==0 )
    {
        ReturnWithErrors($G_Resource, array(), ERR_POSTEMPTY);
    }
    else
    {
        # take action based on which submit button was pressed
        switch (isset($_POST["Submit"]) ? $_POST["Submit"] : NULL)
        {
        case "Add":
            # save changes to record
            $EmptyFields = UpdateResource($G_Resource, $G_User);

            # if some required fields were not filled out
            if (count($EmptyFields))
            {
                # return to editing page with error
                ReturnWithErrors($G_Resource, $EmptyFields, ERR_REQUIREDFIELDEMPTY);
            }
            else
            {
                # convert temporary record to permanent
                $G_Resource->IsTempResource(FALSE);

                # update creation timestamp for record if using the default schema
                if ($Schema->Id() == MetadataSchema::SCHEMAID_DEFAULT)
                {
                    $G_Resource->Set("Date Of Record Creation", date("Y-m-d H:i:s"));
                }

                # update search and recommender DBs (if configured to do so)
                UpdateSearchAndRecommender($G_Resource);
            }
            break;

        case "Save":
            # save changes to record
            $EmptyFields = UpdateResource($G_Resource, $G_User);

            # process image upload requests
            UploadImages($G_Resource, $G_User);

            # process file upload requests
            UploadFiles($G_Resource, $G_User);

            # if some required fields were not filled out
            if (count($EmptyFields))
            {
                # return to editing page with error
                ReturnWithErrors($G_Resource, $EmptyFields, ERR_REQUIREDFIELDEMPTY);
            }
            break;

        case "Duplicate":
            # create duplicate resource
            $Factory = new ResourceFactory($G_Resource->SchemaId());
            $DupResource = $Factory->DuplicateResource($G_Resource->Id());

            # update some default fields if the resource is part of the default
            # metadata schema
            if ($G_Resource->SchemaId() == MetadataSchema::SCHEMAID_DEFAULT)
            {
                # modify likely field to indicate resource is duplicate
                $TitleField = $Schema->GetFieldByMappedName("Title");
                $DescriptionField = $Schema->GetFieldByMappedName("Description");
                if ($TitleField instanceof MetadataField)
                {
                    $DupResource->Set($TitleField,
                            $DupResource->Get($TitleField)." [DUPLICATE]");
                }
                elseif ($DescriptionField instanceof MetadataField)
                {
                    $DupResource->Set($DescriptionField,
                            $DupResource->Get($DescriptionField)." [DUPLICATE]");
                }

                # update the timestamp fields
                $TimestampFields =
                    $Schema->GetFields(MetadataSchema::MDFTYPE_TIMESTAMP);
                foreach ($TimestampFields as $TimestampField)
                {
                    # if the record is not released, blank the timestamp
                    if ($TimestampField->Name() == "Date Of Record Release")
                    {
                        $DupResource->Set($TimestampField, NULL);
                    }
                }

                # Set AddedById to the currently logged in user
                global $G_User;
                $DupResource->Set("Added By Id", $G_User->Get("UserId"));
            }

            # signal that a resource has been duplicated
            $AF->SignalEvent("EVENT_RESOURCE_DUPLICATE", array(
                $DupResource, $G_Resource));

            # return to editing page with duplicate
            $AF->SetJumpToPage("EditResource&ID=".$DupResource->Id());
            break;

        case "Delete":
            # if delete confirmation already requested
            if (isset($_POST["H_DeletionRequested"]))
            {
                # set flag to indicate resource should be deleted
                $G_ResourceDeleted = TRUE;
            }
            else
            {
                # save changes to record
                UpdateResource($G_Resource, $G_User);

                # set flag to indicate need to ask for delete confirmation
                $G_DeleteRequested = TRUE;
            }
            break;

        case "Cancel":
            # if cancelling resource deletion
            if (isset($_POST["H_DeletionRequested"]))
            {
                # set flag to indicate that deletion was cancelled
                $G_DeletionCancelled = TRUE;
            }
            else
            {
                # if this was a new resource being added
                if ($G_Resource->IsTempResource())
                {
                    # set flag to indicate that adding a new resource was cancelled
                    $G_AddingCancelled = TRUE;
                }
                else
                {
                    # set flag to indicate that editing was cancelled
                    $G_EditingCancelled = TRUE;
                }
            }
            break;

        case "Edit":
            $AF->SetJumpToPage("EditResource&ID="
                               .$G_Resource->Id());
            break;

        case "Upload":
            # return to editing page
            $AF->SetJumpToPage("EditResource&ID=".$G_Resource->Id());

            # save changes to record
            UpdateResource($G_Resource, $G_User);

            # process image upload requests
            UploadImages($G_Resource, $G_User);

            # process file upload requests
            UploadFiles($G_Resource, $G_User);
            break;

        default:
            # save changes to record
            UpdateResource($G_Resource, $G_User);

            # process image upload requests
            UploadImages($G_Resource, $G_User);

            # process file upload requests
            UploadFiles($G_Resource, $G_User);

            # for each controlled name and tree field
            $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_CONTROLLEDNAME
                    | MetadataSchema::MDFTYPE_TREE);
            foreach ($Fields as $Field)
            {
                # if user pressed search button for field
                if (isset($_POST["SearchField_".$Field->Id()]))
                {
                    # jump to search page for field
                    $AF->SetJumpToPage("EditResourceSearchName&ID="
                            .$G_Resource->Id()."&MF=".$Field->Id());
                }
            }

            # for each file or image field
            $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_FILE
                    | MetadataSchema::MDFTYPE_IMAGE);
            foreach ($Fields as $Field)
            {
                # if user has permission to modify field
                if ($G_Resource->UserCanEditField($G_User, $Field))
                {
                    # if files uploaded for this field for this resource
                    $Files = $G_Resource->GetByField($Field, TRUE);
                    if (count($Files))
                    {
                        # for each existing file for field
                        foreach ($Files as $File)
                        {
                            # if user pressed delete button for file
                            if (($Field->Type() == MetadataSchema::MDFTYPE_FILE)
                                    && isset($_POST["DeleteFile_".$File->Id()]))
                            {
                                $AF->SignalEvent(
                                    "EVENT_RESOURCE_FILE_DELETE",
                                    array(
                                        "Field" => $Field,
                                        "Resource" => $G_Resource,
                                        "File" => $File));

                                # detach file from resource
                                $G_Resource->Clear($Field, $File);

                                # return to edit page with appropriate message
                                $AF->SetJumpToPage("EditResource&ID="
                                                   .$G_Resource->Id());
                            }
                            # else if user pressed delete button for image
                            elseif (($Field->Type() == MetadataSchema::MDFTYPE_IMAGE)
                                    && isset($_POST["DeleteImage_".$File->Id()]))
                            {
                                # detach image from resource
                                $G_Resource->Clear($Field, $File);

                                # return to edit page with appropriate message
                                $AF->SetJumpToPage("EditResource&ID="
                                                   .$G_Resource->Id());
                            }
                        }
                    }
                }
            }
            break;
        }
    }
}

# load fields for display usage
$G_Fields = $Schema->GetFields(NULL, MetadataSchema::MDFORDER_EDITING);

function DeleteResourceIfAppropriate($Resource, $ResourceDeleted, $AddingCancelled)
{
    # delete resource if appropriate (now that we are done with it)
    if ($ResourceDeleted || $AddingCancelled)
    {
        if (LocalFunctionExists("ResourceDeletionHook"))
        {
            Local_ResourceDeletionHook($Resource->Id());
        }
        $Resource->Delete();
    }
}
$AF->AddPostProcessingCall("DeleteResourceIfAppropriate",
        $G_Resource, $G_ResourceDeleted, $G_AddingCancelled);
