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

require_once("lib/AxisPHP/Axis--StandardLibrary.php");

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

function PrintSearchTextFormEntries($NumberOfEntries)
{
    global $G_SearchGroups, $G_User;

    # retrieve current search parameters (if any)
    if (isset($G_SearchGroups["MAIN"]["SearchStrings"]))
    {
        # populate with search selections if logged in and not refining a search
        if ($G_User->IsLoggedIn() && !isset($_GET["RF"]))
        {
            $SearchSelections = array();

            $SSData = $G_User->Get("SearchSelections");
            if (!is_null($SSData))
            {
                $SearchSelections = unserialize($SSData);
            }

            if (isset($_GET["FK"]))
            {
                $SearchSelections["F_SearchCat0"] = "Keyword";
            }
        }

        if (empty($SearchSelections))
        {
            $SavedSearchValues = array_values($G_SearchGroups["MAIN"]["SearchStrings"]);
        }

        else
        {
            $Schema = new MetadataSchema();

            $Index = 0;
            foreach( $SearchSelections as $FieldId )
            {
                if ($FieldId === "Keyword")
                {
                    $FieldName = "XXXKeywordXXX";
                }

                else
                {
                    $Field = $Schema->GetField($FieldId);
                    $FieldName = $Field->Name();
                }

                $SavedSearchValues[$Index++] =
                    isset($G_SearchGroups["MAIN"]["SearchStrings"][$FieldName])?
                    $G_SearchGroups["MAIN"]["SearchStrings"][$FieldName] : "";
            }
        }
    }

    # for each field
    for ($Index = 0;  $Index < $NumberOfEntries;  $Index++)
    {
        # retrieve current search parameter for this field (if available)
        $DefaultValue = isset($SavedSearchValues[$Index])
            ? $SavedSearchValues[$Index] : "";

        # print option list and field
        PrintSearchTextFormEntry("F_SearchText".$Index, $DefaultValue, $Index);
    }
}

function PrintSearchTextFieldOptionList($CurrentIndex, $DefaultValue = NULL)
{
    # get list of available metadata fields (if not already retrieved)
    global $G_User, $G_SearchGroups;
    static $FieldList;
    static $FieldListMap;

    # set the field list if not already set
    if (!isset($FieldList))
    {
        $Schema = new MetadataSchema();
        $Fields = $Schema->GetFields(
            MetadataSchema::MDFTYPE_TEXT |
            MetadataSchema::MDFTYPE_PARAGRAPH |
            MetadataSchema::MDFTYPE_CONTROLLEDNAME |
            MetadataSchema::MDFTYPE_NUMBER |
            MetadataSchema::MDFTYPE_FILE |
            MetadataSchema::MDFTYPE_TREE |
            MetadataSchema::MDFTYPE_IMAGE |
            MetadataSchema::MDFTYPE_DATE |
            MetadataSchema::MDFTYPE_TIMESTAMP |
            MetadataSchema::MDFTYPE_URL |
            MetadataSchema::MDFTYPE_REFERENCE);

        foreach ($Fields as $FieldId => $Field)
        {
            if ($Field->Enabled()
                && $Field->IncludeInAdvancedSearch()
                && ($G_User->HasPriv($Field->ViewingPrivilege())
                    || $G_User->HasPriv($Field->EditingPrivilege())
                    || ($Field->ViewingPrivilege() == 0)))
            {
                $FieldList[$FieldId] = $Field->GetDisplayName();
                $FieldListMap[$Field->Name()] = $Field->GetDisplayName();
            }
        }
    }

    # add in keyword search
    $FieldList["Keyword"] = "Keyword";

    # put field in alphabetical order
    asort($FieldList);

    $SearchSelections = array();

    # populate with search selections if logged in and not refining a search
    if ($G_User->IsLoggedIn() && !isset($_GET["RF"]))
    {
        $SSData = $G_User->Get("SearchSelections");

        if (!is_null($SSData))
        {
            $SearchSelections = unserialize($SSData);
        }

        if (isset($_GET["FK"]))
        {
            $SearchSelections["F_SearchCat0"] = "Keyword";
        }
    }

    # Look for a previous user-set value:
    if (isset($SearchSelections["F_SearchCat".$CurrentIndex]))
    {
        $DefaultValueIndex = $SearchSelections["F_SearchCat".$CurrentIndex];
    }

    # if valid default value supplied by caller
    else if ($DefaultValue && isset($FieldListMap[$DefaultValue]))
    {
        # convert default value to value index
        $DefaultValue = $FieldListMap[$DefaultValue];
        $DefaultValueIndex = array_search($DefaultValue, $FieldList);
    }

    else
    {
        # use keyword as default
        $DefaultValueIndex = "Keyword";
    }

    # print option list
    PrintOptionList("F_SearchCat".$CurrentIndex, $FieldList, $DefaultValueIndex);
}

function PrintSearchLimitFormEntries($FieldTypesOrFieldName = NULL)
{
    global $CurrentField;
    global $G_User;

    # for each limit of type specified
    $Schema = new MetadataSchema();
    if (is_string($FieldTypesOrFieldName))
    {
        $Fields = array($Schema->GetFieldByName($FieldTypesOrFieldName));
    }
    else
    {
        $Fields = $Schema->GetFields($FieldTypesOrFieldName);
    }
    foreach ($Fields as $CurrentField)
    {
        # if limit field is marked to be used in Advanced Search
        if ($CurrentField->Enabled()
                && $CurrentField->IncludeInAdvancedSearch()
                && ($G_User->HasPriv($CurrentField->ViewingPrivilege())
                    || $G_User->HasPriv($CurrentField->EditingPrivilege())
                    || ($CurrentField->ViewingPrivilege() == 0)))
        {
            # print entry
            PrintSearchLimitFormEntry(
                $CurrentField->GetDisplayName(),
                $CurrentField->Type());
        }
    }
}

# called in HTML file to display each option list in Limit Search section
function PrintSearchLimitOptionList($DisplayedListLength)
{
    global $G_SearchGroups;
    global $CurrentField;
    global $DB;
    global $ResFactory;
    global $G_User;

    # retrieve values for option list
    if ($CurrentField->Type() == MetadataSchema::MDFTYPE_USER)
    {
        $UserFactory = new CWUserFactory();
        $PossibleValues = $UserFactory->GetUsersWithPrivileges(
                PRIV_RESOURCEADMIN, PRIV_MYRESOURCEADMIN, PRIV_RELEASEADMIN);
    }
    else
    {
        if ($CurrentField->Name() == "Cumulative Rating")
        {
            $PossibleValues = array(
                    20 => "*",
                    40 => "**",
                    60 => "***",
                    80 => "****",
                    100 => "*****",
                    );
        }
        else
        {
            $PossibleValues = $CurrentField->GetPossibleValues();
            asort($PossibleValues);
        }
    }

    # assume no default values
    $DefaultValues = NULL;

    # if saved search available
    $FieldId = $CurrentField->Id();
    if (isset($G_SearchGroups))
    {
        # if default values available
        if (isset($G_SearchGroups[$FieldId]["SearchStrings"][$CurrentField->Name()]))
        {
            # if field is a flag or number
            if ($CurrentField->Type() & (MetadataSchema::MDFTYPE_FLAG|MetadataSchema::MDFTYPE_NUMBER))
            {
                # use value from SearchGroups directly
                $DefaultValues = preg_replace("/^[=><!]+/", "",
                        $G_SearchGroups[$FieldId]["SearchStrings"][$CurrentField->Name()]);
            }
            else
            {
                # convert values to indices to match option list values
                $Values = is_array($G_SearchGroups[$FieldId]["SearchStrings"][$CurrentField->Name()])
                        ? $G_SearchGroups[$FieldId]["SearchStrings"][$CurrentField->Name()]
                        : array($G_SearchGroups[$FieldId]["SearchStrings"][$CurrentField->Name()]);
                $DefaultValues = array();
                foreach ($Values as $Value)
                {
                    $Value = preg_replace("/^[=><!]+/", "", $Value);
                    $DefaultValues[] = array_search($Value, $PossibleValues);
                }
            }
        }
    }

    # add null entry if list is only one element long (so user has a way of selecting "no limit")
    if ($DisplayedListLength == 1)
    {
        $PossibleValues = array("-1" => "--") + $PossibleValues;
        if ($DefaultValues == NULL) {  $DefaultValues = "-1";  }
    }

    # if the field name is longer than any of the possible options, then extend
    # the width of the select box to match it to avoid display funkiness
    $Width = "100%";
    foreach ($PossibleValues as $Value)
    {
        if (strlen($Value) >= strlen($CurrentField->GetDisplayName()))
        {
            $Width = NULL;
            break;
        }
    }

    $CountType = ($G_User->IsLoggedIn() &&
                  $G_User->HasPriv(PRIV_SYSADMIN, PRIV_COLLECTIONADMIN,
                                   PRIV_RELEASEADMIN, PRIV_RESOURCEADMIN)) ?
        "All" : "Released" ;

    $DisabledOptions = array();
    foreach ($PossibleValues as $Value)
    {
        if ($ResFactory->GetResourceCount($FieldId, $Value, $CountType) === 0)
        {
            $DisabledOptions[$Value] = 1;
        }
    }

    # print option list
    PrintOptionList("F_SearchLimit".$FieldId."[]", $PossibleValues,
            $DefaultValues, NULL, $DisplayedListLength,
            TRUE, ($DisplayedListLength > 1), NULL, $Width, $DisabledOptions);
}

# function to return action string for form tag
function GetAdvancedSearchAction()
{
    return("index.php?P=AdvancedSearch");
}

# function to return action string for Saved Search string
function GetSavedSearchAction()
{
    return("index.php?P=SavedSearch");
}

# function to print any error messages at top of the page
function PrintErrorMessages()
{
    global $ErrorMessages;

    # if error messages were passed from PreferencesComplete
    if (isset($ErrorMessages) && is_array($ErrorMessages) &&
        count($ErrorMessages) > 0)
    {
        # print error messages
        print("<ul><b>\n");
        foreach ($ErrorMessages as $Message)
        {
            printf("<li>%s</li>\n", $Message);
        }
        print("</ul></b>\n");
    }
}

# print option list with specified choices for records per page
function PrintRecordsPerPageOptionList()
{
    global $User, $SysConfig;

    $Args = func_get_args();
    $Default = -1;

    # user default
    foreach ($Args as $Arg)
    {
        # add choice to list
        $Choices[$Arg] = $Arg;

        # if default is not yet set and choice is at or above default user's
        # last choice
        if (($Default == -1)
            && ($User->IsLoggedIn())
            && ($User->Get("RecordsPerPage"))
            && ($Arg >= $User->Get("RecordsPerPage")))
        {
            # set default
            $Default = $Arg;
        }
    }

    # global default
    if ($Default == -1)
    {
        $Default = $SysConfig->DefaultRecordsPerPage();
    }

    # print option list
    PrintOptionList("F_RecordsPerPage", $Choices, $Default);
}

# display available saved searches
function DisplayUserSearchList()
{
    global $User;

    # retrieve list of saved searches for current user
    $SSFactory = new SavedSearchFactory();
    $Searches = $SSFactory->GetSearchesForUser($User->Id());

    # if saved searches found
    if (count($Searches))
    {
        # begin search list
        print("<ul class=\"SPTSavedSearches\">\n");

        # for each saved search
        foreach ($Searches as $SearchId => $Search)
        {
            # add entry for search
            $Descrip = addslashes(strip_tags($Search->GetSearchGroupsAsTextDescription()));
            print("<li><a href=\"index.php?P=Advanced"
                  ."&amp;SI=".$Search->GetSearchId()."\" "
                  ."title=\"Search Parameters:\n".$Descrip."\">"
                  .htmlspecialchars($Search->SearchName())."</a></li>\n");
        }

        # end search list
        print("</ul>\n");
    }
    else
    {
        # print messages indicating no searches saved
        print("There are no searches currently saved.");
    }
}

# get number of searches user has saved
function GetSavedSearchCount()
{
    global $User;
    $SSFactory = new SavedSearchFactory();
    $Searches = $SSFactory->GetSearchesForUser($User->Id());
    return count($Searches);
}

function EditingSavedSearch()
{
    global $G_SavedSearch;

    return isset($G_SavedSearch) ? TRUE : FALSE;
}

function PrintSavedSearchName()
{
    global $G_SavedSearch;

    if (isset($G_SavedSearch)) {  print($G_SavedSearch->SearchName());  }
}

function PrintHiddenFormFields()
{
    global $G_SavedSearch;
    if (isset($G_SavedSearch))
    {
        print("<input type=\"hidden\" name=\"F_SearchId\" value=\"".$G_SavedSearch->GetSearchId()."\">\n");
    }

    if (isset($_GET["RF"]))
    {
        print("<input type=\"hidden\" name=\"F_SearchRefinement\" value=\"1\">\n");
    }
}


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

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

# non-standard global variables
global $CurrentField;
global $ErrorMessages;
global $G_SavedSearch;
global $G_SearchGroups;
global $ResFactory;
global $G_SortField;
global $G_SortFields;

$G_SortField = NULL;
$Schema = new MetadataSchema();

$SortFieldId = GetArrayValue(array_merge($_GET, $_POST), "SF");

# sort field specified
if ($SortFieldId)
{
    $Field = $Schema->GetField(intval($SortFieldId));

    if ($Field->Status() == MetadataSchema::MDFSTAT_OK)
    {
        $G_SortField = $Field;
    }
}

if ($User->IsLoggedIn() && isset($_GET["SI"]))
{
    $G_SavedSearch = new SavedSearch($_GET["SI"]);

    # only allow the owner or a system/user admin to view the search
    if ($G_SavedSearch->UserId() == $GLOBALS["User"]->Id()
        || $GLOBALS["User"]->HasPriv(PRIV_SYSADMIN, PRIV_USERADMIN))
    {
        $G_SearchGroups = $G_SavedSearch->SearchGroups();
    }

    # let the user know they can't view it
    else
    {
        $G_SavedSearch = NULL;
        $ErrorMessages[] = "ERROR: You do not have permission to view that search.";
    }
}
elseif (isset($_GET["RF"]))
{
    $G_SearchGroups = SavedSearch::TranslateUrlParametersToSearchGroups($_GET);
}
# PrintForDebug("G_SearchGroups", $G_SearchGroups);

$ResFactory = new ResourceFactory();

PageTitle("Advanced Search");

# load possible sort fields
$G_SortFields[] = array("", "Relevance", is_null($G_SortField));
$PossibleFields = $Schema->GetFields(
    MetadataSchema::MDFTYPE_TEXT |
    MetadataSchema::MDFTYPE_NUMBER |
    MetadataSchema::MDFTYPE_DATE |
    MetadataSchema::MDFTYPE_TIMESTAMP |
    MetadataSchema::MDFTYPE_URL );
$SortFieldId = (!is_null($G_SortField)) ? $G_SortField->Id() : NULL;
foreach ($PossibleFields as $Field)
{
    if ($Field->IncludeInSortOptions()
        && (!$Field->ViewingPrivilege() || $G_User->HasPriv($Field->ViewingPrivilege())))
    {
        $G_SortFields[] =
            array(
                $Field->Id(),
                $Field->GetDisplayName(),
                $Field->Id() == $SortFieldId);
    }
}
