<?PHP

$GLOBALS["G_ErrMsg"] = Upgrade290_PerformUpgrade();

/**
* Perform all of the upgrades for 2.9.0.
* @return
*/
function Upgrade290_PerformUpgrade()
{
    # holds all errors for the upgrade
    $ErrorString = NULL;

    # each error message from the upgrades
    $ErrorMessages = array(
        Upgrade290_MoveFileAndImageStorage(),
        Upgrade290_MigrateAllFieldPrivileges());

    # reduce the erro messages to one string
    foreach ($ErrorMessages as $ErrorMessage)
    {
        $ErrorString .= $ErrorString ? "<br />" . $ErrorMessage : $ErrorMessage;
    }

    return $ErrorString;
}

/**
* Helper which moves file contents of dirs
*/
function Upgrade290_MoveDirContents($SrcDir, $TgtDir)
{
    if (!is_dir($SrcDir))
        return;

    if (!is_dir($TgtDir))
        mkdir($TgtDir);

    $DirHandle = opendir($SrcDir);

    while ( ($DirEntry = readdir($DirHandle)) !== FALSE )
    {
        if (is_file($SrcDir."/".$DirEntry) )
        {
            copy($SrcDir."/".$DirEntry, $TgtDir."/".$DirEntry);
            @unlink($SrcDir."/".$DirEntry);
        }
    }
    closedir($DirHandle);
    @rmdir($SrcDir);
}

/**
* Move the file and image storage directories into local/data
*/
function Upgrade290_MoveFileAndImageStorage()
{
    $Errors = array();

    # Check to make sure that each dir we want to migrate is writable if it exists.
    foreach ( array("ImageStorage", "ImageStorage/Previews",
                    "ImageStorage/Thumbnails", "FileStorage" )
              as $Dir)
    {
        if (is_dir($Dir) && !is_writable($Dir))
        {
            @chmod($Dir, 0777);
            if ( !is_writable($Dir) )
            {
                $Errors []= "Directory <i>".$Dir."</i> is not writable.";
            }
        }
    }

    if (count($Errors)>0)
    {
        return implode("<br>",$Errors );
    }
    else
    {
        Upgrade290_MoveDirContents("ImageStorage/Previews","local/data/images/previews");
        Upgrade290_MoveDirContents("ImageStorage/Thumbnails","local/data/images/thumbnails");
        Upgrade290_MoveDirContents("ImageStorage","local/data/images");

        Upgrade290_MoveDirContents("FileStorage", "local/data/files");

        return "";
    }
}

/**
* Migrate the privileges for all metadata fields.
* @return Returns NULL on success and an error message otherwise.
*/
function Upgrade290_MigrateAllFieldPrivileges()
{
    # get all of the metadata fields
    $Fields = Upgrade290_GetFields();

    # an error occurred when fetching the fields
    if ($Fields === FALSE)
    {
        return "Could not get fetch the metadata fields for privilege migration.";
    }

    # there are no fields, so return
    if (count($Fields) === 0)
    {
        return;
    }

    # hold any errors that occur when migrating the privileges
    $Errors = "";

    # migrate the privileges for each field
    foreach ($Fields as $Field)
    {
        $Errors .= Upgrade290_MigrateFieldPrivileges($Field);
    }

    # There were no errors when migrating the privleges
    if (!strlen($Errors))
    {
        return NULL;
    }

    # return the errors
    return $Errors;
}

/**
* Get all metadata field data.
* @return Returns an array of metadata field data or FALSE if an error occured.
*/
function Upgrade290_GetFields()
{
    $Link = mysqli_connect(
        $GLOBALS["FVars"]["F_DBHost"],
        $GLOBALS["FVars"]["F_DBLogin"],
        $GLOBALS["FVars"]["F_DBPassword"],
        $GLOBALS["FVars"]["F_DBName"]);

    $Result = mysqli_query($Link, "SELECT * FROM MetadataFields");

    # there was an error when executing the query
    if ($Result === FALSE)
    {
        return FALSE;
    }

    # the resulting rows
    $Rows = array();

    # couldn't find any fields
    if (mysqli_num_rows($Result) < 1)
    {
        return $Rows;
    }

    # fetch the rows
    while (NULL !== ($Row = mysqli_fetch_assoc($Result)))
    {
        $Rows[] = $Row;
    }

    # an error occurred because there should be at least one row
    if (!count($Rows))
    {
        return FALSE;
    }

    # return the data
    return $Rows;
}

/**
* Migrate the privileges for one field.
* @param array $Field An array of field data from the database.
* @return Returns NULL on success and an error message otherwise.
*/
function Upgrade290_MigrateFieldPrivileges(array $Field)
{
    $Errors = array();
    $FieldId = $Field["FieldId"];

    $Link = mysqli_connect(
        $GLOBALS["FVars"]["F_DBHost"],
        $GLOBALS["FVars"]["F_DBLogin"],
        $GLOBALS["FVars"]["F_DBPassword"],
        $GLOBALS["FVars"]["F_DBName"]);

    # for each privilege type
    foreach (array("View", "Author", "Edit") as $PrivilegeType)
    {
        # the privilege set data structure
        $PrivilegeSet = array();

        # the old privilege values
        $Privilege = $Field[$PrivilegeType . "ingPrivilege"];
        $UserIsValueLogic = $Field[$PrivilegeType . "ingUserIsValue"];
        $UserValue = $Field[$PrivilegeType . "ingUserValue"];

        # add a privilege if one was set
        if ($Privilege > 0)
        {
            $PrivilegeSet["Privileges"][] = intval($Privilege);
        }

        # add a user is value condition if one was set
        # (MetadataField::USERISVALUE_UNSET = 0)
        if ($UserValue && $UserIsValueLogic != 0)
        {
            $PrivilegeSet["Privileges"][] = array(
                "FieldId" => intval($UserValue),
                "Operator" => "==",
                "Value" => NULL);
        }

        # add the logic for the privilege set (MetadataField::USERISVALUE_AND = 1)
        $PrivilegeSet["Logic"] = $UserIsValueLogic == 1 ? "AND" : "OR";

        # serialize the data so that it can be put in the database
        $PrivilegeSetData = serialize($PrivilegeSet);

        # update the privileges in the database
        $Result = mysqli_query($Link, "
            UPDATE MetadataFields
            SET `".$PrivilegeType."ingPrivileges` = '".addslashes($PrivilegeSetData)."'
            WHERE FieldId = '".addslashes($FieldId)."'");

        # failed to migrate the privileges for the field
        if ($Result === FALSE)
        {
            $SafeFieldName = htmlspecialchars($Field["FieldName"]);
            $SafePrivilegeTypeName = htmlspecialchars(strtolower($PrivilegeType . "ing"));

            $Errors[] = "Could not migrate the " . $SafePrivilegeTypeName
                . " privileges for the ". $SafeFieldName . " field.";
        }
    }

    # no errors, so don't return an error message
    if (!count($Errors))
    {
        return NULL;
    }

    # return the error messages as one string
    return implode("<br />", $Errors);
}
