<?PHP

#
#   FILE:  SPT--GlobalSearchEngine.php
#
#   METHODS PROVIDED:
#       GlobalSearchEngine()
#           - constructor
#       SomeMethod($SomeParameter, $AnotherParameter)
#           - short description of method
#
#   AUTHOR:  Edward Almasy
#
#   Part of CWIS and the Scout Portal Toolkit
#   Copyright 2005 Internet Scout
#   http://scout.wisc.edu
#

/*
OUTSTANDING ISSUES:
- search string(s) must be escaped (~XX)
- search scores must be normalized
*/


class GlobalSearchEngine {

    # ---- PUBLIC INTERFACE --------------------------------------------------

    # object constructor
    function GlobalSearchEngine()
    {
    }

    # perform keyword search
    function Search($SearchString, $StartingResult = 0, $NumberOfResults = 10)
    {
        # save start time to use in calculating search time
        $StartTime = $this->GetMicrotime();

        # create OAI-SQ set specification from search string
        $SetSpec = "OAI-SQ!".$SearchString;

        # perform global search
        $SearchResults = $this->PerformSearch(
                $SetSpec, $StartingResult, $NumberOfResults);

        # record search time
        $this->LastSearchTime = $this->GetMicrotime() - $StartTime;

        # return results to caller
        return $SearchResults;
    }

    # perform search across multiple fields and return trimmed results to caller
    function FieldedSearch($SearchStrings, $StartingResult = 0, $NumberOfResults = 10)
    {
    }

    # report number of results found during last search
    function NumberOfResults() {  return $this->NumberOfResultsAvailable;  }

    # report time taken to perform last search
    function SearchTime()
    {
        return $this->LastSearchTime;
    }


    # ---- PRIVATE INTERFACE -------------------------------------------------

    var $NumberOfResultsAvailable;
    var $LastSearchTime;

    # perform OAI-SQ search
    function PerformSearch($SetSpec, $StartingResult, $NumberOfResults)
    {
        # for each global search site
        $DB = new Database();
        $DB->Query("SELECT * FROM GlobalSearchSites");
        $SearchResults = array();
        while ($SiteInfo = $DB->FetchRow())
        {
            # retrieve results from site
            $SiteSearchResults = $this->SearchSite($SiteInfo, $SetSpec);

            # add results to result list
            $SearchResults = array_merge($SearchResults, $SiteSearchResults);
        }

        # sort the results in descending order by search score
        function SearchScoreCmp($ResultA, $ResultB)
        {
            return ($ResultA["Search Score"] == $ResultB["Search Score"]) ? 0
                    : (($ResultA["Search Score"] < $ResultB["Search Score"]) ? 1 : -1);
        }
        usort($SearchResults, "SearchScoreCmp");

        # save number of results found
        $this->NumberOfResultsAvailable = count($SearchResults);

        # trim result list to match range requested by caller
        $SearchResults = array_slice($SearchResults, $StartingResult, $NumberOfResults);

        # return search results to caller
        return $SearchResults;
    }

    # search one site
    function SearchSite($SiteInfo, $SetSpec)
    {
        # create OAI client and perform query
        $Client = new OAIClient($SiteInfo["OaiUrl"]);
        $Client->SetSpec($SetSpec);
        $QueryResults = $Client->GetRecords();

        # for each result returned from query
        foreach ($QueryResults as $Result)
        {
            # extract and save result data where available
            unset($ResultData);
            $ResultData["Title"] =
                    isset($Result["metadata"]["DC:TITLE"][0])
                    ? $Result["metadata"]["DC:TITLE"][0] : NULL;
            $ResultData["Description"] =
                    isset($Result["metadata"]["DC:DESCRIPTION"][0])
                    ? $Result["metadata"]["DC:DESCRIPTION"][0] : NULL;
            $ResultData["Url"] =
                    isset($Result["metadata"]["DC:IDENTIFIER"][0])
                    ? $Result["metadata"]["DC:IDENTIFIER"][0] : NULL;
            $ResultData["Full Record Link"] =
                    isset($Result["about"]["SEARCHINFO"]["FULLRECORDLINK"][0])
                    ? $Result["about"]["SEARCHINFO"]["FULLRECORDLINK"][0] : NULL;
            $ResultData["Search Score"] =
                    isset($Result["about"]["SEARCHINFO"]["SEARCHSCORE"][0])
                    ? $Result["about"]["SEARCHINFO"]["SEARCHSCORE"][0] : NULL;
            $ResultData["Cumulative Rating"] =
                    isset($Result["about"]["SEARCHINFO"]["CUMULATIVERATING"][0])
                    ? $Result["about"]["SEARCHINFO"]["CUMULATIVERATING"][0] : NULL;
            $ResultData["Cumulative Rating Scale"] =
                    isset($Result["about"]["SEARCHINFO"]["CUMULATIVERATINGSCALE"][0])
                    ? $Result["about"]["SEARCHINFO"]["CUMULATIVERATINGSCALE"][0] : NULL;

            # save site info for result
            $ResultData["Site ID"] = $SiteInfo["SiteId"];
            $ResultData["Site Name"] = $SiteInfo["SiteName"];
            $ResultData["Site URL"] = $SiteInfo["SiteUrl"];

            # add result data to search results
            $SearchResults[] = $ResultData;
        }

        # return search results to caller
        return $SearchResults;
    }

    # convenience function for getting time in microseconds
    function GetMicrotime()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }
}


?>
