Beispiel #1
0
 /**
  * Checks to see if any of the databases currently being searched are restricted
  * to the user, throws Xerxes_Exception_DatabasesDenied if one is not
  *
  * @param array $dbList							list of Xerxes_Data_Database objects
  * @param Xerxes_Framework_Request $objRequest	Xerxes request object
  * @param Xerxes_Framework_Registry $objRegistry Xerxes registry object
  * @return bool 
  */
 public static function checkDbListSearchableByUser($objSearchXml, $objRequest, $objRegistry)
 {
     $search_xml = simplexml_import_dom($objSearchXml->documentElement);
     $deniedList = array();
     foreach ($search_xml->xpath("//database_links/database") as $database) {
         // extract the database info held in the cache and convert it here
         // to a data value object so we can feed it to dbSearchableForUser()
         // which is expecting that
         $db = new Xerxes_Data_Database();
         $db->title_display = (string) $database->title_display;
         $db->searchable = (string) $database->searchable;
         $db->guest_access = (string) $database->guest_access;
         if (count($database->group_restrictions) > 0) {
             foreach ($database->group_restrictions->group_restriction as $restriction) {
                 array_push($db->group_restrictions, (string) $restriction);
             }
         }
         // now check to see if it is allowed to be searched
         if (!self::dbSearchableForUser($db, $objRequest, $objRegistry)) {
             $deniedList[] = $db;
         }
     }
     // if any one of them doesn't match, kill this thing!
     if (count($deniedList) > 0) {
         $e = new Xerxes_Exception_DatabasesDenied();
         $e->setDeniedDatabases($deniedList);
         throw $e;
     } else {
         return true;
     }
 }
 public function doExecute()
 {
     // metalib search object
     $objSearch = $this->getSearchObject();
     // params from the request
     $strQuery = $this->request->getProperty("query");
     $strQuery2 = $this->request->getProperty("query2");
     $strField = $this->request->getProperty("field");
     $strField2 = $this->request->getProperty("field2");
     $strFindOperator = $this->request->getProperty("find_operator1");
     $arrDatabases = $this->request->getProperty("database", true);
     $strSubject = $this->request->getProperty("subject");
     $strSpell = $this->request->getProperty("spell");
     $strContext = $this->request->getProperty("context");
     $strContextUrl = $this->request->getProperty("context_url");
     // configuration options
     $configNormalize = $this->registry->getConfig("NORMALIZE_QUERY", false, false);
     $configBaseUrl = $this->registry->getConfig("BASE_URL", true);
     $configYahooID = $this->registry->getConfig("YAHOO_ID", false, "calstate");
     $configSearchLimit = $this->registry->getConfig("SEARCH_LIMIT", true);
     $configContextUrl = $this->registry->getConfig("LIMIT_CONTEXT_URL", false);
     //  if so configured, ensure that context_url is limited to certain domain(s)
     if ($configContextUrl != null) {
         $bolPassed = Xerxes_Framework_Parser::withinDomain($strContextUrl, $configContextUrl);
         if ($bolPassed == false) {
             throw new Exception("context_url only allowed for specified domains");
         }
     }
     // database communications object
     $objData = new Xerxes_DataMap();
     // if subject is given but not databases, automatically find
     // databases for subject, from first sub-category.
     if ($strSubject != null && count($arrDatabases) == 0) {
         $search_limit = $this->registry->getConfig("SEARCH_LIMIT", true);
         $arrDatabases = array();
         $objSubject = $objData->getSubject(strtolower($strSubject), null, "metalib", null, $this->request->getProperty("lang"));
         // did we find a subject that has subcategories?
         if ($objSubject != null && $objSubject->subcategories != null && count($objSubject->subcategories) > 0) {
             $subs = $objSubject->subcategories;
             $objSubcategory = $subs[0];
             $index = 0;
             // get databases up to search limit from first subcat,
             // add to $arrdatabases.
             foreach ($objSubcategory->databases as $objDatabaseData) {
                 if ($objDatabaseData->searchable == 1) {
                     array_push($arrDatabases, $objDatabaseData->metalib_id);
                     $index++;
                 }
                 if ($index >= $search_limit) {
                     break;
                 }
             }
         }
     }
     // if we have a subject, but no context/contexturl, look
     // them up for the subject. Allows convenient defaults
     // for direct-linking into search results.
     if ($strContext == "" && $strSubject != "") {
         // look up the subject if we haven't already, to get the name.
         if (!isset($objSubject)) {
             $objSubject = $objData->getSubject($strSubject);
         }
         $strContext = $objSubject->name;
     }
     if ($strContextUrl == "" && $strSubject != "") {
         $strContextUrl = $this->request->url_for(array("base" => "databases", "action" => "subject", "subject" => $strSubject));
     }
     // ensure a query and field
     if ($strQuery == "") {
         throw new Exception("text_metasearch_error_no_search_terms");
     }
     if ($strField == "") {
         $strField = "WRD";
     }
     if ($strField2 == "") {
         $strField2 = "WRD";
     }
     if ($strFindOperator == "") {
         $strFindOperator = "AND";
     }
     // get databases
     $arrDB = $objData->getDatabases($arrDatabases);
     // start out database information xml object.
     $objXml = new DOMDocument();
     $objXml->loadXML("<search />");
     // access control for databases
     $excludedDbs = array();
     $excludedIDs = array();
     foreach ($arrDB as $db) {
         if (!Xerxes_Helper::dbSearchableForUser($db, $this->request, $this->registry)) {
             $excludedDbs[] = $db;
             $excludedIDs[] = (string) $db->metalib_id;
         }
     }
     if (count($excludedDbs) > 0) {
         // remove excluded dbs from our db lists. what a pain in php, sorry.
         foreach ($arrDB as $key => $db) {
             if (in_array((string) $db->metalib_id, $excludedIDs)) {
                 unset($arrDB[$key]);
             }
         }
         foreach ($arrDatabases as $key => $id) {
             if (in_array($id, $excludedIDs)) {
                 unset($arrDatabases[$key]);
             }
         }
         // and make a note of the excluded dbs please.
         $excluded_xml = $objXml->createElement("excluded_dbs");
         $objXml->documentElement->appendChild($excluded_xml);
         foreach ($excludedDbs as $db) {
             $element = Xerxes_Helper::databaseToNodeset($db, $this->request, $this->registry);
             $element = $objXml->importNode($element, true);
             $excluded_xml->appendChild($element);
         }
     }
     // ensure correct number of databases selected
     if (count($arrDatabases) < 1 && count($excludedDbs) > 0) {
         $e = new Xerxes_Exception_DatabasesDenied("text_metasearch_error_not_authorized");
         $e->setDeniedDatabases($excludedDbs);
         throw $e;
     } elseif (count($arrDatabases) < 1) {
         throw new Exception("text_metasearch_error_no_databases");
     }
     if (count($arrDatabases) > $configSearchLimit) {
         $labels = Xerxes_Framework_Labels::getInstance();
         $error = $labels->getLabel("text_metasearch_error_too_many_databases");
         $error = sprintf($error, $configSearchLimit);
         throw new Exception($error);
     }
     $strSpellCorrect = "";
     // spelling correction
     $strSpellUrl = "";
     // return url for spelling change
     $strGroup = "";
     // group id number
     $strNormalizedQuery = "";
     // normalized query
     // query parser provides normalization and spell check
     $objQueryParser = new Xerxes_QueryParser();
     // normalize query option is still experimental (2009-04-16)
     $strFullQuery = $objQueryParser->normalizeMetalibQuery($strField, $strQuery, $strFindOperator, $strField2, $strQuery2, $configNormalize);
     // initiate search with Metalib
     $strGroup = $objSearch->search($strFullQuery, $arrDatabases);
     // something went wrong, yo!
     if ($strGroup == "") {
         throw new Exception("Could not initiate search with Metalib server");
     }
     // check spelling unless this is a return submission from a previous spell correction
     $strSpellSuggestions = null;
     if ($strSpell == null) {
         // check spelling
         $strAltYahoo = $this->registry->getConfig("ALTERNATE_YAHOO_LOCATION", false);
         $strSpellCorrect = $objQueryParser->checkSpelling($strQuery, $configYahooID, $strAltYahoo);
         $strSpellCorrect2 = null;
         if ($strQuery2) {
             $strSpellCorrect2 = $objQueryParser->checkSpelling($strQuery2, $configYahooID);
         }
         if ($strSpellCorrect != "" || $strSpellCorrect2 != "") {
             // construct spell check return url with spelling suggestion
             // If both search fields were used (advanced search), spell corrections
             // may be in first, second, or both.
             $strNewQuery = $strQuery;
             $arrSuggestions = array();
             if ($strSpellCorrect) {
                 $strNewQuery = $strSpellCorrect;
                 array_push($arrSuggestions, $strSpellCorrect);
             }
             $strNewQuery2 = $strQuery2;
             if ($strSpellCorrect2) {
                 $strNewQuery2 = $strSpellCorrect2;
                 array_push($arrSuggestions, $strSpellCorrect2);
             }
             $strSpellSuggestions = join(" ", $arrSuggestions);
             $strSpellUrl = "./?base=metasearch&action=search&spell=1&query=" . urlencode($strNewQuery) . "&field=" . $strField;
             if ($strNewQuery2) {
                 $strSpellUrl .= "&query2=" . urlencode($strNewQuery2) . "&field2=" . $strField2;
             }
             $strSpellUrl .= "&context=" . urlencode($strContext);
             $strSpellUrl .= "&context_url=" . urlencode($strContextUrl);
             foreach ($arrDatabases as $strDatabase) {
                 if ($strDatabase != null) {
                     $strSpellUrl .= "&database=" . $strDatabase;
                 }
             }
         }
     }
     // create search information xml
     $arrSearch = array();
     $arrSearch["date"] = date("Y-m-d");
     $arrSearch["spelling"] = $strSpellSuggestions;
     $arrSearch["spelling_url"] = $strSpellUrl;
     $arrSearch["context"] = $strContext;
     $arrSearch["context_url"] = $strContextUrl;
     foreach ($arrSearch as $key => $value) {
         $objElement = $objXml->createElement($key, Xerxes_Framework_Parser::escapeXml($value));
         $objXml->documentElement->appendChild($objElement);
     }
     $objPair = $objXml->createElement("pair");
     $objPair->setAttribute("position", 1);
     $objXml->documentElement->appendChild($objPair);
     $arrQuery = array();
     $arrQuery["query"] = $strQuery;
     $arrQuery["field"] = $strField;
     $arrQuery["normalized"] = $strFullQuery;
     foreach ($arrQuery as $key => $value) {
         $objElement = $objXml->createElement($key, Xerxes_Framework_Parser::escapeXml($value));
         $objPair->appendChild($objElement);
     }
     // add second pair if present.
     if ($strQuery2) {
         $objOperator = $objXml->createElement("operator", $strFindOperator);
         $objOperator->setAttribute("position", 1);
         $objXml->documentElement->appendChild($objOperator);
         $objPair = $objXml->createElement("pair");
         $objPair->setAttribute("position", 2);
         $objXml->documentElement->appendChild($objPair);
         $arrQuery = array();
         $arrQuery["query"] = $strQuery2;
         $arrQuery["field"] = $strField2;
         foreach ($arrQuery as $key => $value) {
             $objElement = $objXml->createElement($key, Xerxes_Framework_Parser::escapeXml($value));
             $objPair->appendChild($objElement);
         }
     }
     // get links from ird records for those databases that have been included in the search and
     // store it here so we can get at this information easily on any subsequent page without having
     // to go back to the database
     $objDatabaseLinks = $objXml->createElement("database_links");
     $objXml->documentElement->appendChild($objDatabaseLinks);
     foreach ($arrDB as $objDatabase) {
         // create a database node and append to database_links
         $objNodeDatabase = Xerxes_Helper::databaseToLinksNodeset($objDatabase, $this->request, $this->registry);
         $objNodeDatabase = $objXml->importNode($objNodeDatabase, true);
         $objDatabaseLinks->appendChild($objNodeDatabase);
     }
     // add any warnings from metalib
     $objWarnings = $objSearch->getWarnings();
     if ($objWarnings != null) {
         $objImport = $objXml->importNode($objWarnings->documentElement, true);
         $objXml->documentElement->appendChild($objImport);
     }
     $strGroup = $this->getSearchDate() . "-" . $strGroup;
     // save this information in the cache
     $this->setCache($strGroup, "search", $objXml);
     // redirect to hits page
     $arrParams = array("base" => "metasearch", "action" => "hits", "group" => $strGroup);
     $this->saveCache();
     $this->request->setRedirect($this->request->url_for($arrParams));
     return 1;
 }