/** * Check spelling * * @param QueryTerms[] $query_terms */ public function checkSpelling(array $query_terms) { $registry = Registry::getInstance(); $app_id = $registry->getConfig('BING_ID', true); $suggestion = new Suggestion(); $client = Factory::getHttpClient(); // @todo: see if we can't collapse multiple terms into a single spellcheck query foreach ($query_terms as $term) { $query = $term->phrase; $query = urlencode(trim($query)); $correction = null; // get spell suggestion try { $url = "http://api.search.live.net/xml.aspx?Appid={$app_id}&sources=spell&query={$query}"; $response = $client->getUrl($url); // process it $xml = Parser::convertToDOMDocument($response); // echo header("Content-Type: text/xml"); echo $xml->saveXML(); exit; $suggestion_node = $xml->getElementsByTagName('Value')->item(0); if ($suggestion_node != null) { $correction = $suggestion_node->nodeValue; } } catch (\Exception $e) { trigger_error('Could not process spelling suggestion: ' . $e->getTraceAsString(), E_USER_WARNING); } // got one if ($correction != null) { $term->phrase = $suggestion_node->nodeValue; $suggestion->addTerm($term); } } return $suggestion; }
/** * Check spelling * * @param array of QueryTerms $query_terms */ public function checkSpelling(array $query_terms) { $config = Config::getInstance(); $id = $config->getConfig("SUMMON_ID", false); $key = $config->getConfig("SUMMON_KEY", false); $suggestion = new Suggestion(); if ($id != null && $key != null) { $client = new SummonClient($id, $key, Factory::getHttpClient()); // @todo: see if we can't collapse multiple terms into a single spellcheck query foreach ($query_terms as $term_original) { $term = clone $term_original; $query = $term->phrase; $query = urlencode(trim($query)); $correction = null; // get spell suggestion try { $correction = $client->checkSpelling($query); } catch (\Exception $e) { throw $e; // @todo: remove after testing trigger_error('Could not process spelling suggestion: ' . $e->getTraceAsString(), E_USER_WARNING); } // got one if ($correction != null) { $term->phrase = $correction; $suggestion->addTerm($term); } } } return $suggestion; }
/** * Create Worldcat Search Engine */ public function __construct($role, $source) { parent::__construct(); $config_key = $this->config->getConfig("WORLDCAT_API_KEY", true); $config_always_guest = $this->config->getConfig("WORLDCAT_SEARCH_AS_GUEST", false); // worldcat search object $this->worldcat_client = new Worldcat($config_key, Factory::getHttpClient()); $this->group = new ConfigGroup(); // if user is a guest, make it open, and return it pronto, since we // can't use the limiters below if ($role == "guest" || $config_always_guest != null) { $this->worldcat_client->setServiceLevel("default"); } elseif ($source != "") { $this->group = $this->config->getWorldcatGroup($source); // no workset grouping, please if ($this->group->frbr == "false") { $this->worldcat_client->setWorksetGroupings(false); } // limit to certain libraries if ($this->group->libraries_include != null) { $this->worldcat_client->limitToLibraries($this->group->libraries_include); } // exclude certain libraries if ($this->group->libraries_exclude != null) { $this->worldcat_client->excludeLibraries($this->group->libraries_exclude); } // limit results to specific document types; a limit entry will // take presidence over any format specifically excluded if ($this->group->limit_material_types != null) { $this->worldcat_client->limitToMaterialType($this->group->limit_material_types); } elseif ($this->group->exclude_material_types != null) { $this->worldcat_client->excludeMaterialType($this->group->exclude_material_types); } } }
/** * Create new Voyager availability lookup object */ public function __construct() { $this->config = Config::getInstance(); $this->server = $this->config->getConfig('server', true); $this->server = rtrim($this->server, '/') . '/'; $ignore = $this->config->getConfig('ignore_locations', false); $this->ignore_locations = explode(";", $ignore); $this->client = Factory::getHttpClient(); }
/** * Constructor */ public function __construct() { parent::__construct(); $id = $this->config->getConfig("SUMMON_ID", true); $key = $this->config->getConfig("SUMMON_KEY", true); $this->summon_client = new Summon($id, $key, Factory::getHttpClient()); // formats to exclude $this->formats_exclude = explode(',', $this->config->getConfig("EXCLUDE_FORMATS")); }
/** * Parses a validation response from a CAS server to see if the returning CAS request is valid * * @param string $results xml or plain text response from cas server * @return bool true if valid, false otherwise * @exception throws exception if cannot parse response or invalid version */ private function isValid() { // values from the request $ticket = $this->request->getParam("ticket"); // configuration settings $configCasValidate = $this->registry->getConfig("CAS_VALIDATE", true); $configCasValidate = rtrim($configCasValidate, '/'); // figure out which type of response this is based on the service url $arrURL = explode("/", $configCasValidate); $service = array_pop($arrURL); // now get it! $url = $configCasValidate . "?ticket=" . $ticket . "&service=" . urlencode($this->validate_url); $client = Factory::getHttpClient(); $req = $client->get($url); $req->getCurlOptions()->set(CURLOPT_SSL_VERIFYHOST, false); $req->getCurlOptions()->set(CURLOPT_SSL_VERIFYPEER, false); $response = $req->send(); $results = (string) $response->getBody(); // validate is plain text if ($service == "validate") { $message_array = explode("\n", $results); if (count($message_array) >= 2) { if ($message_array[0] == "yes") { return $message_array[1]; } } else { throw new \Exception("Could not parse CAS validation response."); } } elseif ($service == "serviceValidate" || $service == "proxyValidate") { // these are XML based $xml = Parser::convertToDOMDocument($results); $cas_namespace = "http://www.yale.edu/tp/cas"; $user = $xml->getElementsByTagNameNS($cas_namespace, "user")->item(0); $failure = $xml->getElementsByTagNameNS($cas_namespace, "authenticationFailure")->item(0); if ($user != null) { if ($user->nodeValue != "") { return $user->nodeValue; } else { throw new \Exception("CAS validation response missing username value"); } } elseif ($failure != null) { // see if error, rather than failed authentication if ($failure->getAttribute("code") == "INVALID_REQUEST") { throw new \Exception("Invalid request to CAS server: " . $failure->nodeValue); } } else { throw new \Exception("Could not parse CAS validation response."); } } else { throw new \Exception("Unsupported CAS version."); } // if we got this far, the request was invalid return false; }
public function __construct($command) { $config = Config::getInstance(); $this->apiurl = $config->getConfig("apiurl"); $this->client = Factory::getHttpClient(); $this->client->setUri($this->apiurl . $command); $api_data = $this->client->send()->getBody(); $api_data = json_decode($api_data, true); $api_data = array_pop($api_data); $i = 1; foreach ($api_data as $k => $v) { $api_data[$k]['position'] = $i++; } $this->api_data = $api_data; }
public function getTotal(Query $query) { $total = 0; $url = $this->getUrl($query); $client = Factory::getHttpClient(); $response = $client->getUrl($url); // extract the total number of hits in the results page; $arrMatches = array(); if (preg_match('/\\(1-[0-9]{1,2} of ([0-9]{1,10})\\)/', $response, $arrMatches) != 0) { $total = (int) $arrMatches[1]; } elseif (!stristr($response, "No matches found") && !stristr($response, "NO ENTRIES FOUND")) { $total = 1; // only found one response, catalog jumped right to full display } return $total; }
/** * Constructor * */ public function __construct($type, $targets) { // full set of Targets from Search25 API $this->config = Config::getInstance(); $url = $this->config->getConfig("apiurl"); $command = '/institutions.json?active=true'; $this->client = Factory::getHttpClient(); $this->client->setUri($url . $command); $api_institutions = $this->client->send()->getBody(); if ($type == null) { $command = "/z3950server.json?active=true"; } else { $command = "/z3950server.json?active=true&source_type={$type}"; } $this->client->setUri($url . $command); $api_targets = $this->client->send()->getBody(); $api_institutions = json_decode($api_institutions, true); $api_institutions = array_pop($api_institutions); $api_targets = json_decode($api_targets, true); $api_targets = array_pop($api_targets); $tgtArray = array(); foreach ($api_targets as $api_target) { $data = array(); $key = $api_target['m25_code']; $data['pz2_key'] = $key; $data['z3950_location'] = $api_target['z39_name']; $data['linkback_url'] = $api_target['linkback_url']; $i = 0; while ($api_institutions[$i]['m25_code'] != $key) { $i++; } $data['short_name'] = $api_institutions[$i]['short_name']; $data['display_name'] = htmlentities($api_institutions[$i]['full_name']); $data['sort_name'] = htmlentities($api_institutions[$i]['sort_name']); $data['library_url'] = $api_institutions[$i]['library_url']; $data['domain'] = $api_institutions[$i]['domain']; $target = new Target(); $target->load($data); $tgtArray[] = $target; } usort($tgtArray, array($this, 'alphasort')); for ($i = 0; $i < count($tgtArray); $i++) { $tgt = $tgtArray[$i]; $tgt->position = $i + 1; $this->targets[$tgt->pz2_key] = $tgt; } }
/** * Do the actual search and return results * * @param Query $search search object * @param int $start [optional] starting record number * @param int $max [optional] max records * @param string $sort [optional] sort order * @param bool $facets [optional] whether to include facets * * @return Results */ protected function doSearch(Search\Query $search, $start = 1, $max = 10, $sort = "", $facets = true) { $results = new Search\ResultSet($this->config); $query = $search->toQuery(); $this->url = $this->server . "/search?q=" . urlencode($query); if ($this->config->getConfig('client')) { $this->url .= '&client=' . urlencode($this->config->getConfig('client')); } if ($this->config->getConfig('site')) { $this->url .= '&site=' . urlencode($this->config->getConfig('site')); } $this->url .= '&output=xml'; // google results are 0-based if ($start != null) { $start = $start - 1; $this->url .= '&start=' . $start; } // echo $this->url; exit; $client = Factory::getHttpClient(); $google_results = $client->getUrl($this->url, 3); $xml = simplexml_load_string($google_results); // header("Content-type: text/xml"); echo $xml->saveXML(); exit; $x = 0; // exact matches foreach ($xml->GM as $gm) { $record = new Record(); $record->loadXML($gm); $results->addRecord($record); } // regular results $results_array = $xml->xpath("//RES"); if (count($results_array) > 0 && $results_array !== false) { $results_xml = $results_array[0]; $results->total = (int) $results_xml->M; foreach ($results_xml->R as $result_xml) { if ($x >= $max) { break; } $record = new Record(); $record->loadXML($result_xml); $results->addRecord($record); $x++; } } return $results; }
/** * Create new Innopac availability lookup object * * @param string $server server address */ public function __construct() { $this->config = Config::getInstance(); $this->server = $this->config->getConfig('server', true); $this->server = rtrim($this->server, '/'); $this->innreach = $this->config->getConfig('innreach', false, false); $this->convert_to_utf8 = $this->config->getConfig('convert_to_utf8', false, false); $availability_status = explode(';', $this->config->getConfig('available_statuses', true)); foreach ($availability_status as $status) { $this->availability_status[] = trim($status); } $ignore_locations = explode(';', $this->config->getConfig('ignore_locations', true)); foreach ($ignore_locations as $location) { $this->locations_to_ignore[] = trim($location); } $this->client = Factory::getHttpClient(); }
/** * Constructor * */ public function __construct($pz2_key) { // full set of Libraries for this institution from Search25 API $this->config = Config::getInstance(); $url = $this->config->getConfig("apiurl"); $command = "/institutions/{$pz2_key}/libraries.json?active=true"; $this->client = Factory::getHttpClient(); $this->client->setUri($url . $command); $api_libraries = $this->client->send()->getBody(); $api_libraries = json_decode($api_libraries, true); $api_libraries = array_pop($api_libraries); $arr = array(); foreach ($api_libraries as $api_library) { $library = new Library(); $api_library['pz2_key'] = $pz2_key; $library->load($api_library); $arr[] = $library; } usort($arr, array($this, 'alphasort')); $this->libraries = $arr; }
public function getRecommendations(Xerxes\Record $xerxes_record, $min_relevance = 0, $max_records = 10) { $bx_records = array(); // now get the open url $open_url = $xerxes_record->getOpenURL(null, $this->sid); $open_url = str_replace('genre=unknown', 'genre=article', $open_url); // send it to bx service $url = $this->url . "/recommender/openurl?token=" . $this->token . "&{$open_url}" . "&res_dat=source=global&threshold={$min_relevance}&maxRecords={$max_records}"; try { $client = Factory::getHttpClient(); $client->setUri($url); $client->setConfig(array('timeout' => 4)); $xml = $client->send()->getBody(); if ($xml == "") { throw new \Exception("No response from bx service"); } } catch (\Exception $e) { // just issue the exception as a warning trigger_error("Could not get result from bX service: " . $e->getTraceAsString(), E_USER_WARNING); return $bx_records; } // header("Content-type: text/xml"); echo $xml; exit; $doc = new \DOMDocument(); $doc->recover = true; $doc->loadXML($xml); $xpath = new \DOMXPath($doc); $xpath->registerNamespace("ctx", "info:ofi/fmt:xml:xsd:ctx"); $records = $xpath->query("//ctx:context-object"); foreach ($records as $record) { $bx_record = new Record(); $bx_record->loadXML($record); array_push($bx_records, $bx_record); } if (count($bx_records) > 0) { // first one is the record we want to find recommendations for // so skip it; any others are actual recommendations array_shift($bx_records); } return $bx_records; }
/** * Constructor * */ public function __construct() { // full set of Subjects from API $this->config = Config::getInstance(); $this->url = $this->config->getConfig("apiurl"); $command = '/subjects.json?active=true'; $this->client = Factory::getHttpClient(); $this->client->setUri($this->url . $command); $api_subjects = $this->client->send()->getBody(); $api_subjects = json_decode($api_subjects, true); $api_subjects = array_pop($api_subjects); $subjArray = array(); foreach ($api_subjects as $sub) { $subject = new Subject(); $subject->load(array('name' => $sub['subject'], 'id' => $sub['subject_id'], 'position' => $sub['subject_id'], 'url' => $sub['ukat_url'])); $subjArray[] = $subject; } usort($subjArray, array($this, 'alphasort')); for ($i = 0; $i < count($subjArray); $i++) { $subj = $subjArray[$i]; $subj->setPosition($i); $this->subjects[] = $subj; } }
/** * Metalib Client * * Static here so we maintain the session id */ public static function getMetalibClient() { if (!self::$client instanceof Metalib) { $config = Config::getInstance(); $address = $config->getConfig("METALIB_ADDRESS", true); $username = $config->getConfig("METALIB_USERNAME", true); $password = $config->getConfig("METALIB_PASSWORD", true); self::$client = new Metalib($address, $username, $password, Factory::getHttpClient()); } return self::$client; }
/** * Fetch list of databases * * @param bool $force_new get data from ebsco * @return array */ public function getDatabases($force_new = false) { $cache = new Cache(); $id = 'ebsco_databases'; if ($force_new == false) { // do we have it already? if (count($this->databases) > 0) { return $this->databases; } // check the cache $this->databases = $cache->get($id); if ($this->databases != null) { return $this->databases; } } // fetch 'em from ebsco $url = $this->host . '/Info?' . 'prof=' . $this->username . '&pwd=' . $this->password; $client = Factory::getHttpClient(); $response = $client->getUrl($url); $xml = new \DOMDocument(); $loaded = $xml->loadXML($response); if ($loaded == true) { $nodes = $xml->getElementsByTagName('db'); if ($nodes->length > 1) { foreach ($nodes as $db) { if ((string) $db->getAttribute('dbType') == 'Regular') { $id = (string) $db->getAttribute('shortName'); $name = (string) $db->getAttribute('longName'); $this->databases[$id] = $name; } } // cache 'em $cache->set($id, $this->databases); } } return $this->databases; }
/** * Do the actual search * * @param mixed $search search object or string * @param string $database [optional] database id * @param int $start [optional] starting record number * @param int $max [optional] max records * @param string $sort [optional] sort order * * @return Results */ protected function doSearch($search, $database, $start, $max, $sort = "relevance") { // default for sort if ($sort == "") { $sort = "relevance"; } // prepare the query $query = ""; if ($search instanceof Search\Query) { $query = $search->toQuery(); } else { $query = $search; } // databases $databases = array(); // we asked for this database specifically if ($database != "") { $databases = array($database); } else { // see if any supplied as facet limit foreach ($search->getLimits(true) as $limit) { array_push($databases, $limit->value); } // nope if (count($databases) == 0) { // get 'em from config $databases_xml = $this->config->getConfig("EBSCO_DATABASES"); if ($databases_xml == "") { throw new \Exception("No databases defined"); } foreach ($databases_xml->database as $database) { array_push($databases, (string) $database["id"]); } } } // construct url $this->url = "http://eit.ebscohost.com/Services/SearchService.asmx/Search?" . "prof=" . $this->username . "&pwd=" . $this->password . "&authType=&ipprof=" . "&query=" . urlencode($query) . "&startrec={$start}&numrec={$max}" . "&sort={$sort}" . "&format=detailed"; // add in the databases foreach ($databases as $database) { $this->url .= "&db={$database}"; } // get the xml from ebsco $client = Factory::getHttpClient(); $client->setUri($this->url); $response = $client->send()->getBody(); // testing // echo "<pre>$this->url<hr>$response</pre>"; exit; if ($response == null) { throw new \Exception("Could not connect to Ebsco search server"); } // load it in $xml = new \DOMDocument(); $xml->recover = true; $xml->loadXML($response); // result set $results = new Search\ResultSet($this->config); // get total $total = 0; $hits = $xml->getElementsByTagName("Hits")->item(0); if ($hits != null) { $total = (int) $hits->nodeValue; } ### hacks until ebsco gives us proper hit counts, they are almost there $check = 0; foreach ($xml->getElementsByTagName("rec") as $hits) { $check++; } // no hits, but we're above the first page, so the user has likely // skipped here, need to increment down until we find the true ceiling if ($check == 0 && $start > $max) { // but let's not get crazy here if ($this->deincrementing <= 8) { $this->deincrementing++; $new_start = $start - $max; return $this->doSearch($query, $databases, $new_start, $max, $sort); } } // we've reached the end prematurely, so set this to the end $check_end = $start + $check; if ($check < $max) { if ($check_end < $total) { $total = $check_end; } } ## end hacks // set total $results->total = $total; // add records foreach ($this->extractRecords($xml) as $record) { $results->addRecord($record); } // add clusters $facets = $this->extractFacets($xml); $results->setFacets($facets); return $results; }
/** * Do the actual fetch of an individual record * * @param string record identifier * @return ResultSet */ protected function doGetRecord($id) { $query = $this->getQuery(); $request = $query->getRecordUrl($id); $client = Factory::getHttpClient(); $response = $client->getUrl($request->url, null, $request->headers); return $this->parseResponse($response); }
/** * Establish a new session with EDS * * @param string $profile * @return string */ public function createSession($profile) { $url = $this->server . 'createsession?profile=' . urlencode($profile); $client = Factory::getHttpClient(); $xml = $client->getUrl($url, 10); $dom = new \DOMDocument(); $dom->loadXML($xml); // header('Content-type: text/xml'); echo $dom->saveXML(); exit; $session_id = $dom->getElementsByTagName('SessionToken')->item(0)->nodeValue; return $session_id; }
/** * Do the actual search * * @param mixed $search string or Query, the search query * @param int $start [optional] starting record number * @param int $max [optional] max records * @param string $sort [optional] sort order * * @return Results */ protected function doSearch($search, $start = 1, $max = 10, $sort = "") { // parse the query $query = ""; if ($search instanceof Search\Query) { foreach ($search->getQueryTerms() as $term) { $query .= "&query=" . $term->field_internal . ",contains," . urlencode($term->phrase); } foreach ($search->getLimits(true) as $limit) { $query .= "&query=facet_" . $limit->field . ",exact," . urlencode($limit->value); } } else { $query = "&query=" . urlencode($search); } // on campus as string $on_campus = "true"; if ($this->on_campus == false) { $on_campus = "false"; } // create the url $this->url = $this->server . "/xservice/search/brief?" . "institution=" . $this->institution . "&onCampus=" . $on_campus . $query . "&indx={$start}" . "&bulkSize={$max}"; if ($this->vid != "") { $this->url .= "&vid=" . $this->vid; } foreach ($this->loc as $loc) { $this->url .= "&loc=" . $loc; } if ($sort != "") { $this->url .= "&sortField={$sort}"; } // get the response $client = Factory::getHttpClient(); $client->setUri($this->url); $response = $client->send()->getBody(); // echo $response; if ($response == "") { throw new \Exception("Could not connect to Primo server"); } // load it $xml = Parser::convertToDOMDocument($response); // parse it return $this->parseResponse($xml); }
public function __construct() { $config = Config::getInstance(); $this->apiurl = $config->getConfig("apiurl"); $this->client = Factory::getHttpClient(); }
/** * Do the actual search * * @param string|Query $search search object or string * @param int $start [optional] starting record number * @param int $max [optional] max records * @param string $sort [optional] sort order * @param bool $include_facets [optional] whether to include facets or not * * @return string */ protected function doSearch($search, $start, $max = 10, $sort = null, $include_facets = true) { // start if ($start > 0) { $start--; // solr is 0-based } ### parse the query $query = ""; // passed in a query object, so handle this if ($search instanceof Search\Query) { $query = $search->toQuery(); } else { $query = "&q=" . urlencode($search); } ### now the url $this->url = $this->server . $query; $this->url .= "&start={$start}&rows=" . $max . "&sort=" . urlencode($sort); if ($include_facets == true) { $this->url .= "&facet=true&facet.mincount=1"; foreach ($this->config->getFacets() as $facet => $attributes) { $sort = (string) $attributes["sort"]; $max = (string) $attributes["max"]; $this->url .= "&facet.field={$facet}"; if ($sort != "") { $this->url .= "&f.{$facet}.facet.sort={$sort}"; } if ($max != "") { $this->url .= "&f.{$facet}.facet.limit={$max}"; } } } // make sure we get the score $this->url .= "&fl=*+score"; ## get and parse the response // get the data $client = Factory::getHttpClient(); $client->setUri($this->url); $response = $client->send()->getBody(); $xml = simplexml_load_string($response); if ($response == null || $xml === false) { throw new \Exception("Could not connect to search engine."); } // parse the results $results = new Search\ResultSet($this->config); // extract total $results->total = (int) $xml->result["numFound"]; // extract records foreach ($this->extractRecords($xml) as $record) { $results->addRecord($record); } // extract facets $results->setFacets($this->extractFacets($xml)); return $results; }