<?PHP
#
#   FILE:  EditClassifications.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2013 Edward Almasy and Internet Scout Research Group
#   http://scout.wisc.edu/cwis/
#

# ----- EXPORTED FUNCTIONS ---------------------------------------------------

/**
* Get the classification hierarchy ending at the given classification.
* @param Classification $Classification The classification to end at.
* @return Returns an array of classifications for the hierarchy.
*/
function GetClassificationHierarchy(Classification $Classification)
{
    $Hierarchy = array($Classification);

    # add the classifications in reverse order
    while ($Classification->ParentId() > 0)
    {
        $Classification = new Classification($Classification->ParentId());

        # stop if we find a bad classification
        if ($Classification->Status() !== Classification::CLASSSTAT_OK)
        {
            break;
        }

        $Hierarchy[] = $Classification;
    }

    # reverse the hierarchy so that it is in the correct order
    $Hierarchy = array_reverse($Hierarchy);

    return $Hierarchy;
}

# ----- LOCAL FUNCTIONS ------------------------------------------------------

/**
* Get the parent classification to use.
* @return Returns a classification or NULL if there is no parent to use.
*/
function GetParentClassification()
{
    $ParentId = GetArrayValue($_GET, "ParentId");

    # a parent ID was given in the URL
    if (isset($ParentId))
    {
        $Classification = new Classification($ParentId);

        # return the field ID of the classification if the classification is
        # valid
        if ($Classification->Status() === Classification::CLASSSTAT_OK)
        {
            return $Classification;
        }
    }

    return NULL;
}

/**
* Get the metadata schema to use.
* @param Classification $Parent Optional parent to use as context.
* @return Returns a metadata schema object.
*/
function GetSchema(Classification $Parent=NULL)
{
    # give priority to the parent ID
    if (!is_null($Parent))
    {
        try
        {
            $Field = new MetadataField($Parent->FieldId());

            if ($Field->Status() === MetadataSchema::MDFSTAT_OK)
            {
                return new MetadataSchema($Field->SchemaId());
            }
        } catch (Exception $Exception) {}
    }

    # use the schema ID from the URL or the default schema if not given
    $SchemaId = GetArrayValue($_GET, "SC", MetadataSchema::SCHEMAID_DEFAULT);
    return new MetadataSchema($SchemaId);
}

/**
* Get the metadata field to use.
* @param Classification $Parent Optional parent to use as context.
* @param MetadataSchema $Schema Optional schema to use for context.
* @return Returns a metadata field or NULL if one couldn't be retrieved.
*/
function GetField(Classification $Parent=NULL, MetadataSchema $Schema=NULL)
{
    # give priority to the parent ID
    if (!is_null($Parent))
    {
        try
        {
            $Field = new MetadataField($Parent->FieldId());

            if ($Field->Status() === MetadataSchema::MDFSTAT_OK)
            {
                return $Field;
            }
        } catch (Exception $Exception) {}
    }

    # try to get the field ID from the URL
    $FieldId = GetArrayValue($_GET, "FieldId");

    # a field ID was given in the URL
    if (isset($FieldId))
    {
        try
        {
            $Field = new MetadataField($FieldId);

            if ($Field->Status() === MetadataSchema::MDFSTAT_OK)
            {
                return $Field;
            }
        } catch (Exception $Exception) {}
    }

    # try to use the system configuration if using the default metadata schema
    if ($Schema->Id() === MetadataSchema::SCHEMAID_DEFAULT)
    {
        $Field = $Schema->GetField($GLOBALS["G_SysConfig"]->BrowsingFieldId());

        # return the field ID if the field exists and is okay
        if ($Field instanceof MetadataField
            && $Field->Status() === MetadataSchema::MDFSTAT_OK)
        {
            return $Field;
        }
    }

    # get the tree fields in alphabetical order
    $TreeFields = $Schema->GetFields(
        MetadataSchema::MDFTYPE_TREE,
        MetadataSchema::MDFORDER_ALPHABETICAL);

    # return the first tree field alphabetically if there are any tree fields or
    # return NULL
    return count($TreeFields) ? array_shift($TreeFields) : NULL;
}

/**
* Get all of the classifications for the given parent classification or the
* given metadata field to use for fetching the top-level classifications failing
* that.
* @param Classification $Parent The parent classification.
* @param MetadataField $Field The field to use if the parent isn't given.
* @return Returns an array of classifications when there are less than
* NumClassesPerBrowsePage of them, and an array of arrays of
* classifications (one per alphabet letter) otherwise.
*/
function GetClassifications(
    Classification $Parent=NULL,
    MetadataField $Field=NULL)
{
    # won't be able to fetch any classifications
    if (is_null($Field) && is_null($Parent))
    {
        return array();
    }

    $Database = new Database();

    $Database->Caching(FALSE);

    # get classifications for the given parent classification
    if ($Parent !== NULL)
    {
        $Database->Query("
            SELECT * FROM Classifications
            WHERE ParentId=".intval($Parent->Id())."
            AND FieldId=".intval($Parent->FieldId())."
            ORDER BY ClassificationName");
    }

    # otherwise, try to get the top-level classifications for the field
    else if (!is_null($Field))
    {
        $Database->Query("
            SELECT * FROM Classifications
            WHERE Depth = 0
            AND FieldId = '".intval($Field->Id())."'
            ORDER BY ClassificationName");
    }

    global $SysConfig;

    $Partition = $Database->NumRowsSelected() > $SysConfig->NumClassesPerBrowsePage();

    $Classifications = array();

    while (($Row = $Database->FetchRow()) !== FALSE)
    {
        if ($Partition)
        {
            $Index = strtolower( substr( $Row["ClassificationName"], 0, 1) );
            if (! preg_match("/[a-z]/", $Index))
                $Index = "XX";
            $Classifications[$Index] [] = $Row["ClassificationId"];
        }
        else
        {
            $Classifications []= $Row["ClassificationId"];
        }
    }

    return $Classifications;
}

# ----- MAIN -----------------------------------------------------------------

global $H_Schema;
global $H_Field;
global $H_Parent;
global $H_Classifications;
global $H_ClassificationCount;
global $H_StartLetter;

PageTitle("Add/Edit Classifications");

# check if current user is authorized to edit classifications
if (!CheckAuthorization(PRIV_SYSADMIN, PRIV_CLASSADMIN)) {  return;  }

$H_Parent = GetParentClassification();
$H_Schema = GetSchema($H_Parent);
$H_Field = GetField($H_Parent, $H_Schema);

$ClassList = GetClassifications($H_Parent, $H_Field);

if (isset($ClassList["XX"]))
{
    $H_ClassificationCount = 0;
    foreach ($ClassList as $ClassBin)
        $H_ClassificationCount += count($ClassBin);

    if (!isset($_GET["SL"]))
        $H_StartLetter = "XX";
    else
        $H_StartLetter = strtolower( substr( $_GET["SL"], 0, 1));

    $ClassList = $ClassList[$H_StartLetter];
}
else
{
    $H_ClassificationCount = count($ClassList);
}

$H_Classifications = array();
foreach ($ClassList as $ClassificationId)
    $H_Classifications []= new Classification($ClassificationId);