<?PHP
#
#   FILE:  AdvancedSearch.php
#
#   FUNCTIONS PROVIDED:
#       FunctionName($Parameter, $Parameter)
#           - brief description of function supplied for use in HTML file
#
#   FUNCTIONS EXPECTED:
#       FunctionName($Parameter, $Parameter)
#           - brief description of function that HTML file must supply
#
#   OPTIONAL FUNCTIONS:
#       FunctionName($Parameter, $Parameter)
#           - brief description of function that HTML file may supply
#
#   FORM FIELD ("PUT") PARAMETERS EXPECTED:
#       F_ReleaseFlag
#           - ?
#       F_AddedBy
#           - ?
#       F_LastModifiedBy
#           - ?
#       F_MaxRecords
#           - ?
#       F_SearchCat[N]
#           - IDs (?) indicating which metadata field F_SearchText parameters apply to
#       F_SearchText[N]
#           - text to search for
#       Submit
#           - ?
#
#   URL ("GET") PARAMETERS EXPECTED:
#       Q
#           - if set to "Y" indicates that GET parameters should be used to specify search
#       F<field ID>
#           - contains the search text for the field specified by <field ID> (e.g. F2=text)
#       G<field ID>
#           - contains a dash-separated list of controlled name IDs for the option field
#               specified by <field ID> (e.g. G23=4-12-87)
#       SR
#           - starting index of range of search results to display (first result is at index 0)
#       RP
#           - number of results per page
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2011 Internet Scout Project
#   http://scout.wisc.edu/
#

PageTitle("Search Results");

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

# return AllResourcesFlagged flag
function AllResourcesFlagged()
{
    global $AllResourcesFlagged;
    return $AllResourcesFlagged;
}

# get count of flagged files
function GetFlaggedFilesCount()
{
    global $User;

    $InputPath = substr(__FILE__, 0, strrpos(__FILE__, '/')).
        "/tmp/InputData.". $User->Get("UserId");

    $ResourceCount = 0;

    if (is_readable($InputPath))
    {
        $fpi = fopen($InputPath, "r");
        while (!feof($fpi))
        {
            $ResourceId = fgets($fpi, 4096);
            $ResourceId = trim($ResourceId);

            if (empty($ResourceId))
                break;

            $ResourceCount++;
        }
    }
    return $ResourceCount;
}

# print resource entry found as a result of an advanced search
function PrintSearchResults()
{
    global $G_User;
    global $G_SearchResults;
    global $G_Engine;

    # if this is a global search
    if (IsGlobalSearch())
    {
        # for each search result
        foreach ($G_SearchResults as $SearchResult)
        {
            PrintGlobalSearchResult($SearchResult);
        }
    }
    else
    {
        # for each search result
        foreach ($G_SearchResults as $ResourceId => $Score)
        {
            $Resource = new Resource($ResourceId);

            $FullRecordUrl = "index.php?P=FullRecord&amp;ID=".$ResourceId;
            $FullRecordUrl .= "&amp;ReturnText=".urlencode("Search Results");
            $FullRecordUrl .= "&amp;ReturnTo=".urlencode(
                "index.php?".http_build_query($_GET));

            PrintSearchResult($Resource,
                $FullRecordUrl,
                $Resource->UserCanEdit($G_User),
                "index.php?P=EditResource&amp;ID=".$ResourceId,
                $Resource->ScaledCumulativeRating(), NULL, TRUE, TRUE,
                $G_User->HasPriv(PRIV_SYSADMIN), $G_Engine->SearchTerms());
        }
    }
}

function PrintExternalSearchResults()
{
    global $G_ExternalSearchResults;

    # for each external search result
    foreach ($G_ExternalSearchResults as $Source => $Results)
    {
        print $Results;
    }
}

function PrintSearchString()
{
    global $G_SearchCriteria;

    print($G_SearchCriteria);
}

function PrintTotalNumberOfResults()
{
    global $G_Engine;

    print($G_Engine->NumberOfResults());
}

function PrintStartingResultNumber()
{
    global $G_StartingResult;
    global $G_Engine;

    if ($G_Engine->NumberOfResults() == 0)
    {
        print("0");
    }
    else
    {
        print($G_StartingResult + 1);
    }
}

function PrintEndingResultNumber()
{
    global $G_StartingResult;
    global $G_RecordsPerPage;
    global $G_Engine;

    print(min(($G_StartingResult + $G_RecordsPerPage), $G_Engine->NumberOfResults()));
}

function PreviousResultsAvailable()
{
    global $G_StartingResult;

    return ($G_StartingResult > 0) ? TRUE : FALSE;
}

function NextResultsAvailable()
{
    global $G_StartingResult;
    global $G_RecordsPerPage;
    global $G_Engine;

    return (($G_StartingResult + $G_RecordsPerPage) < $G_Engine->NumberOfResults()) ? TRUE : FALSE;
}

function PrintPreviousResultsLink()
{
    global $G_StartingResult;
    global $G_RecordsPerPage;
    global $Editing;
    global $G_SearchGroupsForUrl;
    global $G_SortParamsForUrl;

    $NewStartingResult = max(($G_StartingResult - $G_RecordsPerPage), 0);
    print("index.php?P=AdvancedSearch"
          ."&amp;Q=Y&amp;".$G_SearchGroupsForUrl
          ."&amp;RP=".$G_RecordsPerPage
          ."&amp;SR=". $NewStartingResult
          .(IsGlobalSearch() ? "&amp;GS=Y" : "").$G_SortParamsForUrl);
}

function PrintNextResultsLink()
{
    global $G_StartingResult;
    global $G_RecordsPerPage;
    global $Editing;
    global $G_SearchGroupsForUrl;
    global $G_SortParamsForUrl;

    $NewStartingResult = $G_StartingResult + $G_RecordsPerPage;
    print("index.php?P=AdvancedSearch"
          ."&amp;Q=Y&amp;".$G_SearchGroupsForUrl
          ."&amp;RP=".$G_RecordsPerPage.
          "&amp;SR=".$NewStartingResult
          .(IsGlobalSearch() ? "&amp;GS=Y" : "").$G_SortParamsForUrl);
}

function NoResultsFound()
{
    global $G_Engine;

    return ($G_Engine->NumberOfResults() == 0) ? TRUE : FALSE;
}

function PrintSearchTime()
{
    global $G_Engine;

    printf("%.3f", $G_Engine->SearchTime());
}

function PrintNumberOfPreviousResults()
{
    global $G_RecordsPerPage;

    print($G_RecordsPerPage);
}

function PrintNumberOfNextResults()
{
    global $G_RecordsPerPage;
    global $G_StartingResult;
    global $G_Engine;

    print(min($G_RecordsPerPage, ($G_Engine->NumberOfResults() - ($G_StartingResult + $G_RecordsPerPage))));
}

# return TRUE/FALSE indicating whether global search is available
function GlobalSearchIsAvailable()
{
return FALSE;
}

# return TRUE/FALSE indicating whether a global search was performed
function IsGlobalSearch()
{
    global $G_DoingGlobalSearch;
    return $G_DoingGlobalSearch;
}

# print URL for running global search
function PrintGlobalSearchLink()
{
    global $G_SearchGroupsForUrl;
    global $G_RecordsPerPage;

    print("index.php?P=AdvancedSearch"
          ."&amp;Q=Y&amp;".$G_SearchGroupsForUrl
          ."&amp;RP=".$G_RecordsPerPage
          ."&amp;SR=0&amp;GS=Y");
}

# print URL for running local search
function PrintLocalSearchLink()
{
    global $G_SearchGroupsForUrl;
    global $G_RecordsPerPage;

    print("index.php?P=AdvancedSearch"
          ."&amp;Q=Y&amp;".$G_SearchGroupsForUrl
          ."&amp;RP=".$G_RecordsPerPage
          ."&amp;SR=0");
}

function PrintExportHiddenVars()
{
    global $G_SearchGroupsForUrl;
    global $G_RecordsPerPage;
    global $G_StartingResult;
    global $G_ExportFlagMsg;
    ?>
    <input type="hidden" name="F_ExportRequest" value="Y">
    <input type="hidden" name="F_SearchGroupsForUrl" value="<?PHP  print($G_SearchGroupsForUrl);  ?>">
    <input type="hidden" name="F_RecordsPerPage" value="<?PHP  print($G_RecordsPerPage);  ?>">
    <input type="hidden" name="F_StartingResult" value="<?PHP  print($G_StartingResult);  ?>">
    <?PHP
}

function PrintExportMessage()
{
    global $G_ExportFlagMsg;
    if (isset($G_ExportFlagMsg))
    {
        print("<p><b>".$G_ExportFlagMsg."</b></p>\n");
    }
    elseif (isset($_GET["EFM"]))
    {
        print("<p><b>".$_GET["EFM"]."</b></p>\n");
    }
}

function PrintFastRewindFirstLink()
{
    global $G_RecordsPerPage;
    global $G_SearchGroupsForUrl;
    global $G_SortParamsForUrl;

    print "index.php?P=AdvancedSearch&amp;Q=Y&amp;".$G_SearchGroupsForUrl
        ."&amp;RP=".$G_RecordsPerPage.(IsGlobalSearch() ? "&amp;GS=Y" : "")
        .$G_SortParamsForUrl."&amp;SR=0";
}

function PrintFastRewind20PercentLink()
{
    global $G_TotalPages;
    global $G_CurrentPage;
    global $G_RecordsPerPage;
    global $G_SearchGroupsForUrl;
    global $G_SortParamsForUrl;

    # need to subtract 1 from total since the first result is result number 0
    $StartingResult = ($G_CurrentPage-1-ceil($G_TotalPages/5))*$G_RecordsPerPage;

    print "index.php?P=AdvancedSearch&amp;Q=Y&amp;".$G_SearchGroupsForUrl
        ."&amp;RP=".$G_RecordsPerPage.(IsGlobalSearch() ? "&amp;GS=Y" : "")
        .$G_SortParamsForUrl."&amp;SR=".$StartingResult;
}

function PrintFastForward20PercentLink()
{
    global $G_TotalPages;
    global $G_CurrentPage;
    global $G_RecordsPerPage;
    global $G_SearchGroupsForUrl;
    global $G_SortParamsForUrl;

    # need to subtract 1 from total since the first result is result number 0
    $StartingResult = (ceil($G_TotalPages/5)+$G_CurrentPage-1)*$G_RecordsPerPage;

    print "index.php?P=AdvancedSearch&amp;Q=Y&amp;".$G_SearchGroupsForUrl
        ."&amp;RP=".$G_RecordsPerPage.(IsGlobalSearch() ? "&amp;GS=Y" : "")
        .$G_SortParamsForUrl."&amp;SR=".$StartingResult;
}

function PrintFastForwardLastLink()
{
    global $G_TotalPages;
    global $G_CurrentPage;
    global $G_RemainingPages;
    global $G_RecordsPerPage;
    global $G_SearchGroupsForUrl;
    global $G_SortParamsForUrl;

    # need to subtract 1 from total since the first result is result number 0
    $StartingResult = ($G_TotalPages - 1) * $G_RecordsPerPage;

    print "index.php?P=AdvancedSearch&amp;Q=Y&amp;".$G_SearchGroupsForUrl
        ."&amp;RP=".$G_RecordsPerPage.(IsGlobalSearch() ? "&amp;GS=Y" : "")
        .$G_SortParamsForUrl."&amp;SR=".$StartingResult;
}

function GetSortOrderDetails(MetadataField $Field = NULL)
{
    $Ascending = array(
        "Message" => "Display the results in ascending order",
        "Text" => array("", ""),
        "Width" => 25);
    $Descending = array(
        "Message" => "Display the results in descending order",
        "Text" => array("", ""),
        "Width" => 25);

    # relevance or rating
    if (is_null($Field) || $Field->Name() == "Cumulative Rating")
    {
        $Ascending["Text"] = array("Lo", "Hi");
        $Descending["Text"] = array("Hi", "Lo");
        $Ascending["Width"] = 30;
        $Descending["Width"] = 30;
    }

    # based on field type
    else
    {
        switch ($Field->Type())
        {
            case MetadataSchema::MDFTYPE_NUMBER:
                $Ascending["Text"] = array("2", "1");
                $Descending["Text"] = array("1", "2");
                break;
            case MetadataSchema::MDFTYPE_DATE:
            case MetadataSchema::MDFTYPE_TIMESTAMP:
                $Ascending["Text"] = array("JAN", "DEC");
                $Descending["Text"] = array("DEC", "JAN");
                $Ascending["Width"] = 35;
                $Descending["Width"] = 35;
                break;
            default:
                $Ascending["Text"] = array("A", "Z");
                $Descending["Text"] = array("Z", "A");
                break;
        }
    }

    return array($Ascending, $Descending);
}

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

# retrieve search criteria from search form values
function RetrieveSearchCriteriaFromFormValues()
{
    global $DB;

    # start with empty list of criteria
    $Criteria = array();

    # if this was actually just a keyword ("quick") search
    if (isset($_POST["F_SearchString"]))
    {
        # if there was a search string supplied
        if (strlen(trim($_POST["F_SearchString"])))
        {
            # add keyword string to search criteria
            $Criteria["MAIN"]["SearchStrings"]["XXXKeywordXXX"] =
                    $_POST["F_SearchString"];
        }
    }
    else
    {
        # while there are search text fields left to examine
        $FieldIndex = 0;
        $Schema = new MetadataSchema();
        while (isset($_POST["F_SearchCat".$FieldIndex]))
        {
            # if value is available for box
            if (isset($_POST["F_SearchText".$FieldIndex])
                    && (strlen($_POST["F_SearchText".$FieldIndex])
                        || is_array($_POST["F_SearchText".$FieldIndex])))
            {
                # retrieve metadata field info for box
                if ($_POST["F_SearchCat".$FieldIndex] == "Keyword")
                {
                    $FieldName = "XXXKeywordXXX";
                }
                else
                {
                    $Field = $Schema->GetField($_POST["F_SearchCat".$FieldIndex]);
                    $FieldName = $Field->Name();
                }

                # if value represents multiple values
                $Value = $_POST["F_SearchText".$FieldIndex];
                if (is_array($Value))
                {
                    # for each value
                    foreach ($Value as $SingleValue)
                    {
                        # add value to search criteria
                        $Criteria[$Field->Id()]["SearchStrings"][$FieldName][] = "=".$Field->GetValueForId($SingleValue);
                    }
                }
                else
                {
                    # add value to search criteria
                    if (isset($Criteria["MAIN"]["SearchStrings"][$FieldName]))
                    {
                        $Criteria["MAIN"]["SearchStrings"][$FieldName] .= " ".$Value;
                    }
                    else
                    {
                        $Criteria["MAIN"]["SearchStrings"][$FieldName] = $Value;
                    }
                }
            }

            # move to next search box
            $FieldIndex++;
        }

        # for each possible limit field
        $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_OPTION | MetadataSchema::MDFTYPE_USER | MetadataSchema::MDFTYPE_FLAG | MetadataSchema::MDFTYPE_NUMBER);
        foreach ($Fields as $FieldId => $Field)
        {
            $FieldId = $Field->Id();
            $FieldType = $Field->Type();
            $FieldName = $Field->Name();

            # if value is available for this field
            if (isset($_POST["F_SearchLimit".$FieldId])
                    && is_array($_POST["F_SearchLimit".$FieldId]))
            {
                $SearchLimit = $_POST["F_SearchLimit".$FieldId];

                # if flag field
                if ($Field->Type() == MetadataSchema::MDFTYPE_FLAG)
                {
                    # add flag value to search criteria (if meaningful)
                    if ($_POST["F_SearchLimit".$FieldId][0] >= 0)
                    {
                        $Criteria[$Field->Id()]["SearchStrings"][$Field->Name()][] =
                                "=".$_POST["F_SearchLimit".$FieldId][0];
                    }
                }
                # else if numeric field
                elseif ($Field->Type() == MetadataSchema::MDFTYPE_NUMBER)
                {
                    # add flag value to search criteria (if meaningful)
                    if ($_POST["F_SearchLimit".$FieldId][0] >= 0)
                    {
                        $Criteria[$Field->Id()]["SearchStrings"][$Field->Name()][] =
                                ">=".$_POST["F_SearchLimit".$FieldId][0];
                    }
                }
                # else if user field
                elseif ($FieldType == MetadataSchema::MDFTYPE_USER)
                {
                    $SearchStrings = array();
                    $Logic = SearchEngine::LOGIC_OR;

                    # get privileged users for validation if not set
                    if (!isset($PrivilegedUsers))
                    {
                        $UserFactory = new UserFactory($DB);
                        $PrivilegedUsers = $UserFactory->GetUsersWithPrivileges(
                            PRIV_RESOURCEADMIN,
                            PRIV_MYRESOURCEADMIN,
                            PRIV_RELEASEADMIN);
                    }

                    foreach ($SearchLimit as $UserId)
                    {
                        # meaningful user ID
                        if (0 < $UserId && isset($PrivilegedUsers[$UserId]))
                        {
                            $PrivilegedUser = $PrivilegedUsers[$UserId];

                            $SearchStrings[] = "=" . $PrivilegedUser;
                        }
                    }

                    # add search group only if there are search strings
                    if (0 < count($SearchStrings))
                    {
                        $Criteria[$FieldId]["Logic"] = $Logic;
                        $Criteria[$FieldId]["SearchStrings"][$FieldName] =
                            $SearchStrings;
                    }
                }
                # else
                else
                {
                    # retrieve possible values for field
                    $PossibleValues = $Field->GetPossibleValues();

                    # for each value
                    $Values = $_POST["F_SearchLimit".$FieldId];
                    foreach ($Values as $Value)
                    {
                        # if value is meaningful
                        if (isset($PossibleValues[$Value]))
                        {
                            # add value to search criteria
                            $Criteria[$Field->Id()]["SearchStrings"][$Field->Name()][] = "=".$PossibleValues[$Value];
                        }
                    }
                }
            }
        }
    }

    # set search logic
    foreach ($Criteria as $GroupIndex => $Group)
    {
        $Criteria[$GroupIndex]["Logic"] = ($GroupIndex == "MAIN") ? SearchEngine::LOGIC_AND : SearchEngine::LOGIC_OR;
    }

    # return search criterial to caller
    return $Criteria;
}

function SaveSearchSelections()
{
    # Save the search categories for re-use
    global $G_User;

    if ($G_User->IsLoggedIn())
    {
        $SearchSelections = array();

        $CatNo=0;
        while (isset($_POST["F_SearchCat".$CatNo]) && $CatNo<4)
        {
            if (! ($CatNo == 0 &&
                   isset($_GET["ST"]) &&
                   $_GET["ST"]=="Quick" &&
                   $_POST["F_SearchCat".$CatNo] == "Keyword"))
            {
                $SearchSelections["F_SearchCat".$CatNo] = $_POST["F_SearchCat".$CatNo];
            }
            $CatNo++;
        }
        if (!empty($SearchSelections))
        {
            $G_User->Set("SearchSelections", serialize($SearchSelections));
        }
    }
}

# handle user request to flag resources for export
function HandleExportFlaggingRequest($SubmitButtonText)
{
    global $G_SearchGroups;
    global $G_StartingResult;
    global $G_RecordsPerPage;
    global $G_ExportFlagMsg;
    global $SysConfig;
    global $User;

    # get name of file used to hold IDs of resources to be exported
    $ExportFlagFileName = dirname(
        $_SERVER["SCRIPT_FILENAME"])."/tmp/InputData.".
        $User->Get("UserId");

    # if user requested to clear flagged resources
    if ($SubmitButtonText == "Clear Flagged List")
    {
        # clear flagged resource file (if any)
        if (file_exists($ExportFlagFileName)) {  unlink($ExportFlagFileName);  }

        # set message indicating flagged resource list cleared
        $G_ExportFlagMsg = "List of resources flagged for export has been cleared.";
    }
    # else if user requested to flag search results
    elseif (($SubmitButtonText == "Flag Selected for Export")
            || ($SubmitButtonText == "Flag All for Export"))
    {
        # set up search engine
        $Engine = new SPTSearchEngine();
        $Engine->SearchTermsRequiredByDefault($SysConfig->SearchTermsRequired());
        if (function_exists("FilterSearchResults"))
        {
            $Engine->AddResultFilterFunction("FilterSearchResults");
        }
        if (function_exists("Local_FilterSearchResult"))
        {
            $Engine->AddResultFilterFunction("Local_FilterSearchResult");
        }

        # if user requested to flag all search results
        if ($SubmitButtonText == "Flag Selected for Export")
        {
            # run search and retrieve results for current page
            $G_SearchResults = $Engine->GroupedSearch(
                    $G_SearchGroups, $G_StartingResult, $G_RecordsPerPage);

            # for each search result
            $SelectedSearchResults = array();
            foreach ($G_SearchResults as $ResultId => $ResultScore)
            {
                # if result was selected for export
                if (isset($_POST["F_OkayForExport_".$ResultId]))
                {
                    # add to list of selected results
                    $SelectedSearchResults[$ResultId] = $ResultScore;
                }
            }
            $G_SearchResults = $SelectedSearchResults;
        }
        else
        {
            # run search and retrieve all results
            $G_SearchResults = $Engine->GroupedSearch($G_SearchGroups, 0, 999999);
        }

        # if no results were found to flag
        if (count($G_SearchResults) == 0)
        {
            # set message indicating no results found
            $G_ExportFlagMsg = "No resources found to be flagged for export.";
        }
        else
        {
            # read in list of previously selected resources (if any)
            $PreviouslySelectedResources = array();
            if (file_exists($ExportFlagFileName))
            {
                $FileText = file($ExportFlagFileName);
                if ($FileText)
                {
                    foreach ($FileText as $Line)
                    {
                        $PreviouslySelectedResources[] = rtrim($Line);
                    }
                }
            }

            # add list of newly selected resources to previously selected resources
            $NewlySelectedResources = array_keys($G_SearchResults);
            $UpdatedSelectedResources = array_merge(
                    $PreviouslySelectedResources, $NewlySelectedResources);
            $UpdatedSelectedResources = array_unique($UpdatedSelectedResources);

            # if list of selected resources has changed
            if ($UpdatedSelectedResources != $PreviouslySelectedResources)
            {
                # write out new list of selected resources
                $OutFileHndl = fopen($ExportFlagFileName, "w");
                foreach ($UpdatedSelectedResources as $ResourceId)
                {
                    fwrite($OutFileHndl, $ResourceId."\n");
                }
                fclose($OutFileHndl);
            }

            # set message indicating how many results flagged
            $NewlyFlaggedCount = count($UpdatedSelectedResources) - count($PreviouslySelectedResources);
            $G_ExportFlagMsg = $NewlyFlaggedCount." new resources flagged for export.";
        }
    }
}

# (automatically called in StandardPageStart if defined)
function AddJavascript()
{
    global $G_SearchGroupsForUrl;
    global $G_RecordsPerPage;
    global $G_StartingResult;
    global $G_SearchId;
    global $G_ExportFlagMsg;

    # if our URL does not include search info
    if (!strpos($_SERVER["REQUEST_URI"], "Q=Y"))
    {
        # add JavaScript to reset our URL to include search info
        $UrlParameters = "Q=Y&".$G_SearchGroupsForUrl."&RP=".$G_RecordsPerPage."&SR=".$G_StartingResult;
        if (isset($G_ExportFlagMsg))
        {
            $UrlParameters .= "&EFM=".urlencode($G_ExportFlagMsg);
        }
        ?>
        <script><!--
            document.location.href = document.location + '?<?PHP  print($UrlParameters);  ?>';
        --></script>
        <?PHP
    }
    # else add RSS feed info to page header
    else
    {
        global $DB;
        $DB->Query("SELECT * FROM RSSConfiguration");
        $RssInfo = $DB->FetchRow();
        if ($RssInfo["NotifyBrowser"])
        {
            $FeedLink = OurBaseUrl()."index.php?P=RSS"
                ."&amp;Q=Y&amp;".$G_SearchGroupsForUrl;
            ?>
            <link rel="alternate" title="<?PHP  print($RssInfo["ChannelTitle"]);  ?>"
                    href="<?PHP  print($FeedLink);  ?>" type="application/rss+xml" />
            <?PHP
        }
    }
}

function GetRecordsPerPage()
{
    global $User, $SysConfig;

    # passed via the search form
    if (isset($_POST["F_RecordsPerPage"]) && intval($_POST["F_RecordsPerPage"]))
    {
        return intval($_POST["F_RecordsPerPage"]);
    }

    # passed in the URL parameters
    if (isset($_GET["RP"]) && intval($_GET["RP"]))
    {
        return intval($_GET["RP"]);
    }

    # user setting
    if ($User->IsLoggedIn() && $User->Get("RecordsPerPage"))
    {
        return $User->Get("RecordsPerPage");
    }

    # system-wide setting
    return $SysConfig->DefaultRecordsPerPage();
}

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

# non-standard global variables
global $AllResourcesFlagged;
global $Editing;
global $G_DoingGlobalSearch;
global $G_Engine;
global $G_ExportFlagMsg;
global $G_RecordsPerPage;
global $G_SearchCriteria;
global $G_SearchGroups;
global $G_SearchGroupsForUrl;
global $G_SearchGroupsArrayForUrl;
global $G_SearchId;
global $G_SearchResults;
global $G_SortParamsForUrl;
global $G_SortDescending;
global $G_StartingResult;
global $G_TotalPages;
global $G_CurrentPage;
global $G_RemainingPages;
global $G_ExternalSearchResults;

# variable defaults
$G_SortField = NULL;
$G_SortDescending = TRUE;
$G_SortParamsForUrl = "";
$G_ExternalSearchResults = array();

$Schema = new MetadataSchema();

# if search parameters are specified as part of URL
if (isset($_GET["Q"]) && ($_GET["Q"] == "Y"))
{
    # retrieve search parameters from URL
    $G_SearchGroups = SavedSearch::TranslateUrlParametersToSearchGroups($_GET);

    # retrieve search environment from URL
    $G_StartingResult = isset($_GET["SR"]) ? abs(intval($_GET["SR"])) : 0;
    $G_RecordsPerPage = GetRecordsPerPage();

    # default sort field
    $Field = $Schema->GetField(intval($SysConfig->DefaultSortField()));
    if ($Field->Status() == MetadataSchema::MDFSTAT_OK)
    {
        $G_SortField = $Field;
        $G_SortParamsForUrl .= "&amp;SF=".$G_SortField->Id();
    }

    # sort field specified
    if (isset($_GET["SF"]))
    {
        $Field = $Schema->GetField(intval($_GET["SF"]));

        if ($Field->Status() == MetadataSchema::MDFSTAT_OK)
        {
            $G_SortField = $Field;
            $G_SortParamsForUrl .= "&amp;SF=".$G_SortField->Id();
        }
    }

    # sort order specified
    if (isset($_GET["SD"]))
    {
        $G_SortDescending = (bool) intval($_GET["SD"]);
    }

    # sort order defaults for the given sort field
    else if (!is_null($G_SortField))
    {
        switch ($G_SortField->Type())
        {
            case MetadataSchema::MDFTYPE_NUMBER:
            case MetadataSchema::MDFTYPE_DATE:
            case MetadataSchema::MDFTYPE_TIMESTAMP:
                $G_SortDescending = TRUE; break;
            default:
                $G_SortDescending = FALSE; break;
        }
    }

    # sort order default for relevance
    else
    {
        $G_SortDescending = TRUE;
    }

    $G_SortParamsForUrl .= "&amp;SD=".$G_SortDescending;

    # update records per page if changed
    if (isset($_GET["RP"]) && $User->IsLoggedIn()
        && intval($User->Get("RecordsPerPage")) != intval($_GET["RP"])
        && in_array(intval($_GET["RP"]), array(5, 10, 20, 30, 50, 100)))
    {
        $User->Set("RecordsPerPage", intval($_GET["RP"]));
    }
}
# else if search parameters passed as part of "export flagging" form
elseif (isset($_POST["F_ExportRequest"])
        && ($_POST["F_ExportRequest"] == "Y")
        && isset($_POST["Submit"])
        && strlen($_POST["Submit"]))
{
    # retrieve search parameters and environment from export form hidden tags
    $G_StartingResult = intval($_POST["F_StartingResult"]);
    $G_RecordsPerPage = GetRecordsPerPage();
    $G_SearchGroupsForUrl = $_POST["F_SearchGroupsForUrl"];
    $G_SearchGroups = SavedSearch::TranslateUrlParametersToSearchGroups($G_SearchGroupsForUrl);
}
else
{
    # retrieve search parameters from form fields
    $G_SearchGroups = RetrieveSearchCriteriaFromFormValues();

    # retrieve search environment from form fields
    $G_RecordsPerPage = GetRecordsPerPage();
    $G_StartingResult = 0;

    # save search type for logging
    $NewSearchType = isset($_POST["F_SearchString"]) ? "Quick" : "Advanced";
}

# perform sanity check on records per page value
if ($G_RecordsPerPage < 1) {  $G_RecordsPerPage = 10;  }

# build GET parameter string containing search parameters for use in URLs
$G_SearchGroupsForUrl = SavedSearch::TranslateSearchGroupsToUrlParameters($G_SearchGroups);
$G_SearchGroupsArrayForUrl = SavedSearch::TranslateSearchGroupsToUrlParameterArray($G_SearchGroups);

# handle export flagging operation if requested
if (isset($_POST["F_ExportRequest"])
        && ($_POST["F_ExportRequest"] == "Y")
        && isset($_POST["Submit"])
        && strlen($_POST["Submit"]))
{
    HandleExportFlaggingRequest($_POST["Submit"]);
}
# Redirect to home page if spambot field not filled correctly
if ((isset($_POST["F_Spmbt"]) && isset($_POST["F_JscptSpmbt"])) &&
     ($_POST["F_Spmbt"] !== "" || ($_POST["F_JscptSpmbt"] !== "" && $_POST["F_JscptSpmbt"] !== "8304RPC")))
{
    $AF->SetJumpToPage("Home");
    return;
}

# if save search requested (coming from Advanced Search page)
if (isset($_POST["Submit"]) && ($_POST["Submit"] == "Save"))
{
    # if no search parameters were given
    if (!count($G_SearchGroups))
    {
        # set error message and return to Advanced Search page
        $ErrorMessages[] = "ERROR: No search parameters were specified.";
        $Session->PassVariable("ErrorMessages", $ErrorMessages);
        $AF->SetJumpToPage("Advanced&".$G_SearchGroupsForUrl);
    }
    # else if user is logged in
    elseif ($User->IsLoggedIn())
    {
        # if we have a search ID available
        if (isset($_POST["F_SearchId"]))
        {
            # if we have what looks like a valid search name available
            $G_SearchId = $_POST["F_SearchId"];
            if (strlen(trim($_POST["F_SearchName"])))
            {
                # save search
                $SearchName = $_POST["F_SearchName"];
                $Search = new SavedSearch($G_SearchId, $SearchName, NULL, NULL, $G_SearchGroups);

                # jump to search management page
                $AF->SetJumpToPage("SavedSearch");
            }
            else
            {
                # set error message and return to Advanced Search page
                $ErrorMessages[] = "ERROR: You must supply a name for the search to be saved.";
                $Session->PassVariable("ErrorMessages", $ErrorMessages);
                $AF->SetJumpToPage("Advanced&SI=".$G_SearchId."&".$G_SearchGroupsForUrl);
            }
        }
        else
        {
            # jump to search name input page
            $AF->SetJumpToPage("NewSavedSearch&".$G_SearchGroupsForUrl);
        }
    }
    else
    {
        # set error message and return to Advanced Search page
        $ErrorMessages[] = "ERROR: You must log in before saving searches.";
        $Session->PassVariable("ErrorMessages", $ErrorMessages);
        $AF->SetJumpToPage("Advanced&".$G_SearchGroupsForUrl);
    }
}
# else if saved search editing cancelled (coming from Advanced Search page)
elseif (isset($_POST["Submit"]) && ($_POST["Submit"] == "Cancel"))
{
    # jump to search management page
    $AF->SetJumpToPage("SavedSearch");
}
# else if search parameters were not part of URL
elseif (!isset($_GET["Q"]) || ($_GET["Q"] != "Y"))
{
    # reload page with search parameters as part of URL
    $UrlParameters = "Q=Y&".$G_SearchGroupsForUrl
            ."&RP=".$G_RecordsPerPage."&SR=".$G_StartingResult;
    if (isset($G_ExportFlagMsg))
    {
        $UrlParameters .= "&EFM=".urlencode($G_ExportFlagMsg);
    }
    else
    {
        $UrlParameters .= "&ST=".$NewSearchType;
    }
    $AF->SetJumpToPage("AdvancedSearch&".$UrlParameters);
}
# else perform search
else
{
    # build search criteria string to display to user
    $G_SearchCriteria = SavedSearch::TranslateSearchGroupsToTextDescription(
            $G_SearchGroups);

    # if global search requested
    if (isset($_GET["GS"]) && ($_GET["GS"] == "Y"))
    {
        # set flag to indicate we are doing a global search
        $G_DoingGlobalSearch = TRUE;

        # set up global search engine
        $G_Engine = new GlobalSearchEngine();

        # perform keyword search
        $G_SearchResults = $G_Engine->Search(
                $Keywords, $G_StartingResult, $G_RecordsPerPage);

        # page info
        $G_TotalPages = ceil($G_Engine->NumberOfResults() / $G_RecordsPerPage);
        $G_CurrentPage = floor($G_StartingResult / $G_RecordsPerPage)+1;
        $G_RemainingPages = $G_TotalPages - $G_CurrentPage;
    }
    else
    {
        # set up search engine
        $G_Engine = new SPTSearchEngine();
        function FilterOutTempResources($Id) {  return ($Id < 0);  }
        $G_Engine->AddResultFilterFunction("FilterOutTempResources");
        if (function_exists("FilterSearchResults"))
        {
            $G_Engine->AddResultFilterFunction("FilterSearchResults");
        }
        if (function_exists("Local_FilterSearchResult"))
        {
            $G_Engine->AddResultFilterFunction("Local_FilterSearchResult");
        }

        # if user does not have release or resource admin privileges
        if (!$User->HasPriv(PRIV_RELEASEADMIN, PRIV_RESOURCEADMIN))
        {
            # if there is a release flag field
            $ReleaseField = $Schema->GetFieldByName("Release Flag");
            if ($ReleaseField)
            {
                $SearchGroup = array();

                # add condition to show only released resources
                $SearchGroup["SearchStrings"]["Release Flag"] = "=1";
                $SearchGroup["Logic"] = SearchEngine::LOGIC_AND;

                # show resources added by the user, even they they don't have
                # the release or resource admin privileges
                $AddedByField = $Schema->GetFieldByName("Added By Id");
                if ($AddedByField && $User->HasPriv(PRIV_MYRESOURCEADMIN))
                {
                    $SearchGroup["SearchStrings"]["Added By Id"] = "=".$User->Name();
                    $SearchGroup["Logic"] = SearchEngine::LOGIC_OR;
                }

                $G_SearchGroups[$ReleaseField->Id()] = $SearchGroup;
            }
        }

        # get sort-by field
        $FieldName = (is_null($G_SortField)) ? NULL : $G_SortField->Name();

        # signal keyword search if appropriate
        if (isset($G_SearchGroups["MAIN"]["SearchStrings"]["XXXKeywordXXX"]))
        {
            $SignalResult = $AF->SignalEvent("EVENT_KEYWORD_SEARCH",
                    array("Keywords" =>
                    $G_SearchGroups["MAIN"]["SearchStrings"]["XXXKeywordXXX"]));
            $G_SearchGroups["MAIN"]["SearchStrings"]["XXXKeywordXXX"]
                = $SignalResult["Keywords"];

            # perform external search
            $G_ExternalSearchResults = $AF->SignalEvent("EVENT_SEARCH_EXTERNAL", array(
                $G_SearchGroups, $G_StartingResult, $G_RecordsPerPage,
                $FieldName, $G_SortDescending));
        }
        $G_SearchGroups["MAIN"]["Logic"] = ($SysConfig->SearchTermsRequired()) ?
            SearchEngine::LOGIC_AND : SearchEngine::LOGIC_OR ;

        # perform search
        $G_SearchResults = $G_Engine->GroupedSearch(
                $G_SearchGroups, $G_StartingResult, $G_RecordsPerPage,
                $FieldName, $G_SortDescending);

        # page info
        $G_TotalPages = ceil($G_Engine->NumberOfResults() / $G_RecordsPerPage);
        $G_CurrentPage = floor($G_StartingResult / $G_RecordsPerPage)+1;
        $G_RemainingPages = $G_TotalPages - $G_CurrentPage;

        # signal search performed
        $SignalResult = $AF->SignalEvent("EVENT_SEARCH_RESULTS", array(
                "SearchResults" => $G_SearchResults));
        $G_SearchResults = $SignalResult["SearchResults"];
        $SignalResult = $AF->SignalEvent("EVENT_SEARCH_COMPLETE", array(
                "AdvancedSearch" => (isset($_GET["ST"]) &&
                                     ($_GET["ST"]=="Advanced")?TRUE:FALSE),
                "SearchParameters" => $G_SearchGroupsForUrl,
                "SearchResults" => $G_SearchResults));

        # log search (if this is a new search that has search parameters)
        if (isset($_GET["ST"]) && strlen($G_SearchGroupsForUrl))
        {
            $EventLog = new SPTEventLog();
            $EventType = ($_GET["ST"] == "Advanced")
                    ? SptEventLog::SPTEVENT_ADVANCEDSEARCH : SptEventLog::SPTEVENT_SEARCH;
            $EventLog->Log($EventType, $G_SearchGroupsForUrl, $G_Engine->NumberOfResults());
        }
    }

    # 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);
        }
    }
}

SaveSearchSelections();
