public function doExecute() { // ensure this is the same user $strRedirect = $this->enforceUsername(); if ($strRedirect != null) { $this->request->setRedirect($strRedirect); return 1; } $strEmail = ""; // email address $strSubject = ""; // subject entered by the user $strBody = ""; // body of the email $strNotes = ""; // notes entered by the user $strRecords = ""; // results in citation style $headers = ""; // to specify html as the format of the email // get the records from the previous results command $objXml = $this->request->toXML(); // get user entered values $strEmail = $this->request->getProperty("email"); $strSubject = $this->request->getProperty("subject"); $strNotes = $this->request->getProperty("notes"); $strUsername = $this->request->getSession("username"); // get configuration options $configFromEmail = $this->registry->getConfig("EMAIL_FROM", false, null); if ($strEmail == null) { throw new Exception("text_folder_error_no_email"); } // transform the documents to a basic style for now // will give them citation style options in the future $strRecords = Xerxes_Framework_Parser::transform($objXml, "xsl/citation/basic.xsl"); // add notes and records to body $strBody = $strNotes . "\r\n\r\n"; $strBody .= $strRecords; // set an explcit 'from' address if configured if ($configFromEmail != null) { $headers .= "From: {$configFromEmail} \r\n"; } // send the user back out, so they don't step on this again if (mail($strEmail, $strSubject, $strBody, $headers)) { // send the user back out, so they don't step on this again $arrParams = array("base" => "folder", "action" => "output_email", "username" => $strUsername, "message" => "done"); $url = $this->request->url_for($arrParams); $this->request->setRedirect($url); return 1; } else { throw new Exception("text_folder_error_email_not_sent"); } }
/** * Pulls down a compiled list of all database from Metalib and saves in database * */ private function databases() { $arrDatabases = array(); // get all databases and convert to local format $objXml = new DOMDocument(); $objXml = $this->objSearch->allDatabases($this->configInstitute, true, $this->configChunk); $strXml = Xerxes_Framework_Parser::transform($objXml, "xsl/utility/marc-to-database.xsl"); if ($this->request->getProperty("test")) { $objXml->save("metalib.xml"); file_put_contents("xerxes.xml", $strXml); } $strXml = Xerxes_Framework_Parser::transform($objXml, "xsl/utility/marc-to-database.xsl"); // get just the database info $objSimple = new SimpleXMLElement($strXml); $arrDBs = $objSimple->xpath("//database"); if (count($arrDBs) < 1) { throw new Exception("Could not find any databases in the Metalib KB. " . $this->objSearch->getWarnings(true)); } foreach ($arrDBs as $objDatabase) { // populate data object with properties $objData = new Xerxes_Data_Database(); $objData->metalib_id = (string) $objDatabase->metalib_id; $objData->title_display = (string) $objDatabase->title_display; $objData->type = (string) $objDatabase->type; $objData->data = $objDatabase->asXML(); $arrDatabases[$objData->metalib_id] = $objData; } return $arrDatabases; }
public function doExecute() { $objSearch = $this->getSearchObject(); // metalib search object $bolRedirect = false; // final determination to redirect on merge $objStatus = new DOMDocument(); // search status $objMerge = new DOMDocument(); // merge information $iProgress = null; // number of times metalib status polled // params from the request $id = $this->request->getProperty("group"); $strGroup = $this->getGroupNumber(); $strMergeRedirect = $this->request->getProperty("mergeRedirect"); // configuration options $configShowMergedResults = $this->registry->getConfig("IMMEDIATELY_SHOW_MERGED_RESULTS", false, true); $configApplication = $this->registry->getConfig("APPLICATION_SID", false, "calstate.edu:xerxes"); $configFacets = $this->registry->getConfig("FACETS", false, false); $configRecordsPerPage = $this->registry->getConfig("RECORDS_PER_PAGE", false, 10); $iRefreshSeconds = $this->registry->getConfig("SEARCH_PROGRESS_CAP", false, 35); $configHitsCap = (string) $iRefreshSeconds / 5; $configSortPrimary = $this->registry->getConfig("SORT_ORDER_PRIMARY", false, "rank"); $configSortSecondary = $this->registry->getConfig("SORT_ORDER_SECONDARY", false, "year"); // access control $objSearchXml = $this->getCache($id, "search", "DOMDocument"); Xerxes_Helper::checkDbListSearchableByUser($objSearchXml, $this->request, $this->registry); // redirect link base $arrParams = array("base" => "metasearch", "action" => "results", "group" => $id); // determine if redirect after merge if ($configShowMergedResults == true) { $bolRedirect = true; } if ($strMergeRedirect == "false") { $bolRedirect = false; } else { if ($strMergeRedirect == "true") { $bolRedirect = true; } } // get status of the search and cache result $objStatus = $objSearch->searchStatus($strGroup); $this->setCache($id, "group", $objStatus); // cap the number of refreshes if ($this->request->getSession("refresh-{$strGroup}") != null) { // get refresh count $iProgress = (int) $this->request->getSession("refresh-{$strGroup}"); // if we hit limit, set metalib finish flag to true if ($iProgress >= (int) $configHitsCap) { $objSearch->setFinished(true); } else { $iProgress++; $this->request->setSession("refresh-{$strGroup}", $iProgress); } } else { $this->request->setSession("refresh-{$strGroup}", 1); } // if done see if there are results and merge and redirect, // otherwise this will fall thru and continue with auto refreshing if ($objSearch->getFinished() == true) { $this->request->setSession("refresh-{$strGroup}", 10); // check to see if there are any documents to merge, and then merge // and create facets $iGroupTotal = 0; // total number of hits in the group $arrDatabaseHits = array(); // total number of databases with hits $objSimpleXml = simplexml_import_dom($objStatus->documentElement); $bolSearchLinkHit = false; $strSearchLinkSet = ""; foreach ($objSimpleXml->xpath("//base_info") as $objBase) { if ((string) $objBase->no_of_documents == "888888888") { $bolSearchLinkHit = true; $strSearchLinkSet = (string) $objBase->set_number; } elseif ((int) $objBase->no_of_documents > 0) { // we'll only count the databases with hits $iGroupTotal += (int) $objBase->no_of_documents; array_push($arrDatabaseHits, (string) $objBase->set_number); } } // only got a search-and-link database if ($iGroupTotal == 0 && $bolSearchLinkHit == true) { $arrParams["resultSet"] = $strSearchLinkSet; $this->request->setRedirect($this->request->url_for($arrParams)); return 1; } // got hits if ($iGroupTotal > 0) { // we'll only issue the merge command if there is more than one database // with hits, otherwise there's no point if (count($arrDatabaseHits) == 1) { $strSetNumber = $arrDatabaseHits[0]; // redirect to results page $arrParams["resultSet"] = $strSetNumber; $this->cache->save(); $this->request->setRedirect($this->request->url_for($arrParams)); return 1; } else { $strMergeSet = ""; // merge set identifier $iMergeCount = 0; // count of documents in the merge set // merge the top results $objMerge = $objSearch->merge($strGroup, $configSortPrimary, $configSortSecondary); // get the newly updated status that resulted from that merge // operation and cache $objStatus = $objSearch->searchStatus($strGroup); $this->setCache($id, "group", $objStatus); $objXPath = new DOMXPath($objMerge); // extract new merge set number and total hits for merge set if ($objXPath->query("//new_set_number")->item(0) != null) { $strMergeSet = $objXPath->query("//new_set_number")->item(0)->nodeValue; } if ($objXPath->query("//no_of_documents")->item(0) != null) { $iMergeCount = (int) $objXPath->query("//no_of_documents")->item(0)->nodeValue; } if ($strMergeSet == "") { //throw new Exception( "Result from Metalib returned no set number" ); } // cache the facets response, but only if there are more results than a single page // and facets have been turned on if ($iMergeCount > $configRecordsPerPage && $configFacets == true) { $objFacetXml = $objSearch->facets($strMergeSet, "all", $configApplication); $this->setCache($id, "facets", $objFacetXml); // cache a slimmed down version of the facets as well // to ease the load on the interface $strFacetSlim = Xerxes_Framework_Parser::transform($objFacetXml, "xsl/utility/facets-slim.xsl"); $this->setCache($id, "facets_slim", $strFacetSlim); } } // redirect to results page with merge set if ($bolRedirect == true) { // catch no hits if ($iMergeCount == 0) { // check to see if any of the individual dbs had a search-and-link with // a 'results found' indicator $bolIndividual = false; $strIndividualSet = ""; foreach ($objStatus->getElementsByTagName("base_info") as $objDb) { foreach ($objDb->getElementsByTagName("no_of_documents") as $objDocs) { if ((int) $objDocs->nodeValue > 0) { $bolIndividual = true; if ($objDb->getElementsByTagName("set_number")->item(0) != null) { $strIndividualSet = $objDb->getElementsByTagName("set_number")->item(0)->nodeValue; break 2; } } } } if ($bolIndividual == true) { // redirect to individual results page $arrParams["resultSet"] = $strIndividualSet; $this->cache->save(); $this->request->setRedirect($this->request->url_for($arrParams)); return 1; } } else { // redirect to merged results page $arrParams["resultSet"] = $strMergeSet; $this->cache->save(); $this->request->setRedirect($this->request->url_for($arrParams)); return 1; } } } } // build the response from previous cached data $objXml = new DOMDocument(); $objXml = $this->documentElement(); $objXml = $this->addSearchInfo($objXml, $id); $objXml = $this->addStatus($objXml, $id); $objXml = $this->addProgress($objXml, $this->request->getSession("refresh-{$strGroup}")); $this->request->addDocument($objXml); $this->saveCache(); return 1; }
/** * Simple XSLT transformation function * * @param mixed $xml DOMDocument or string containing xml * @param string $strXslt physical path to xslt document * @param array $arrParams [optional] array of parameters to pass to stylesheet * @param array $arrIncludes [optional] additional stylesheets that should be included in the transform * @return string newly formatted document */ public function transform($xml, $strXslt, $arrParams = null, $arrIncludes = array()) { $html = Xerxes_Framework_Parser::transform($xml, $strXslt, $arrParams, false, $arrIncludes); // as of metalib 4.3 we _still_ need to do this to catch html entity references that // have been escaped for xml compatibility $noEscape = $this->registry->getConfig("FIX_AMERSANDS", false, true); // but make sure we don't do it on an XML output, like the open search option $format = $this->request->getProperty("format"); if ($format == "xml") { $noEscape = false; } if ($noEscape === true) { $html = str_replace("&", "&", $html); } return $html; }
/** * Do something with uncaught errors */ public static function handle($e, Xerxes_Framework_Request $objRequest, Xerxes_Framework_Registry $objRegistry) { if ($objRegistry->getConfig("DISPLAY_ERRORS", false, false)) { throw $e; } // flag certain exception types for special handling in the xslt $strErrorType = get_class($e); // might be a sub-class, reset so view will catch. if ($e instanceof PDOException) { $strErrorType = "PDOException"; } // if this is the command line, just rethrow the error so we can see it; might // make this a little better formatted in the future if ($objRequest->isCommandLine()) { throw $e; } else { // translate heading and message $labels = Xerxes_Framework_Labels::getInstance(); if ($e instanceof Xerxes_Exception) { $heading = $e->heading(); } else { $heading = "text_error"; } $heading = $labels->getLabel($heading); $message = $labels->getLabel($e->getMessage()); // first output to apache error log error_log("Xerxes error: " . $message . ": " . $e->getTraceAsString()); //set proper http response code $resultStatus = 500; if ($e instanceof Xerxes_Exception_AccessDenied) { $resultStatus = 403; } else { if ($e instanceof Xerxes_Exception_NotFound) { $resultStatus = 404; } } header(' ', true, $resultStatus); // send back http status as internal server error or other specified status // for the web, we'll convert the error message to xml along with the type // of exception and hand display off to the error.xsl file $objError = new DOMDocument(); $objError->loadXML("<error />"); $objMessage = $objError->createElement("message", $message); $objMessage->setAttribute("type", $strErrorType); $objError->documentElement->appendChild($objMessage); $objHeading = $objError->createElement("heading", $heading); $objError->documentElement->appendChild($objHeading); // make sure we're showing the main error file $objRegistry->setConfig("XSL_PARENT_DIRECTORY", null); // set the base url for the error.xsl file's benefit; don't want to assume that // the earlier code to this effect was executed before an exception, so this is redundant $base_path = $objRegistry->getConfig('BASE_WEB_PATH', false, ""); $this_server_name = $objRequest->getServer('SERVER_NAME'); // check for a non-standard port $port = $objRequest->getServer('SERVER_PORT'); if ($port == 80 || $port == 443) { $port = ""; } else { $port = ":" . $port; } $protocol = "http://"; if ($objRequest->getServer("HTTPS")) { $protocol = "https://"; } $web = $protocol . $this_server_name . $port . $base_path; $objBaseURL = $objError->createElement("base_url", $web); $objError->documentElement->appendChild($objBaseURL); // if it's a db denied exception, include info on dbs. if ($e instanceof Xerxes_Exception_DatabasesDenied) { $excluded_xml = $objError->createElement("excluded_dbs"); $objError->documentElement->appendChild($excluded_xml); foreach ($e->deniedDatabases() as $db) { $element = Xerxes_Helper::databaseToNodeset($db, $objRequest, $objRegistry); $element = $objError->importNode($element, true); $excluded_xml->appendChild($element); } } // add in the request object's stuff $request_xml = $objRequest->toXML(); $imported = $objError->importNode($request_xml->documentElement, true); foreach ($imported->childNodes as $childNode) { $objError->documentElement->appendChild($childNode); } if ($objRequest->getProperty("format") == "xerxes") { header('Content-type: text/xml'); echo $objError->saveXML(); } else { // display it to the user. Transform will pick up local // xsl for error page too, great. echo Xerxes_Framework_Parser::transform($objError, "xsl/error.xsl"); } } // need to incorporate methods for doing additional actions based on the type // of error -- probably a config option }