示例#1
0
 /**
  * Make Request
  *
  * Makes a request to the Voyager Restful API
  *
  * @param array  $hierarchy Array of key-value pairs to embed in the URL path of
  * the request (set value to false to inject a non-paired value).
  * @param array  $params    A keyed array of query data
  * @param string $mode      The http request method to use (Default of GET)
  * @param string $xml       An optional XML string to send to the API
  *
  * @return obj  A Simple XML Object loaded with the xml data returned by the API
  * @access protected
  */
 protected function makeRequest($hierarchy, $params = false, $mode = "GET", $xml = false)
 {
     // Build Url Base
     $urlParams = "http://{$this->ws_host}:{$this->ws_port}/{$this->ws_app}";
     // Add Hierarchy
     foreach ($hierarchy as $key => $value) {
         $hierarchyString[] = $value !== false ? urlencode($key) . "/" . urlencode($value) : urlencode($key);
     }
     // Add Params
     foreach ($params as $key => $param) {
         $queryString[] = $key . "=" . urlencode($param);
     }
     // Build Hierarchy
     $urlParams .= "/" . implode("/", $hierarchyString);
     // Build Params
     if (isset($queryString)) {
         $urlParams .= "?" . implode("&", $queryString);
     }
     if ($mode == 'GET' && isset($this->getCache[$urlParams])) {
         return $this->getCache[$urlParams];
     }
     // Create Proxy Request
     $client = new Proxy_Request($urlParams);
     if ($this->sessionId) {
         $client->addCookie('JSESSIONID', $this->sessionId);
     }
     // Select Method
     if ($mode == "POST") {
         $client->setMethod(HTTP_REQUEST_METHOD_POST);
         if ($xml) {
             $client->addRawPostData($xml);
         }
     } else {
         if ($mode == "PUT") {
             $client->setMethod(HTTP_REQUEST_METHOD_PUT);
             $client->addRawPostData($xml);
         } else {
             if ($mode == "DELETE") {
                 $client->setMethod(HTTP_REQUEST_METHOD_DELETE);
             } else {
                 $client->setMethod(HTTP_REQUEST_METHOD_GET);
             }
         }
     }
     // Send Request and Retrieve Response
     $startTime = microtime(true);
     if (PEAR::isError($client->sendRequest())) {
         error_log("VoyagerRestful: failed to send request to {$urlParams}");
         return false;
     }
     $code = $client->getResponseCode();
     if ($code >= 400) {
         error_log("VoyagerRestful: HTTP Request failed with error code {$code}. Request url: {$urlParams}, response: " . $client->getResponseBody());
     }
     $cookies = $client->getResponseCookies();
     if ($cookies) {
         foreach ($cookies as $cookie) {
             if ($cookie['name'] == 'JSESSIONID') {
                 $this->sessionId = $cookie['value'];
             }
         }
     }
     $xmlResponse = $client->getResponseBody();
     $this->debugLog('[' . round(microtime(true) - $startTime, 4) . "s] {$this->sessionId} {$mode} request {$urlParams}, body:\n{$xml}\nResults:\n{$xmlResponse}");
     $oldLibXML = libxml_use_internal_errors();
     libxml_use_internal_errors(true);
     $simpleXML = simplexml_load_string($xmlResponse);
     libxml_use_internal_errors($oldLibXML);
     if ($simpleXML === false) {
         $logger = new Logger();
         $error = libxml_get_last_error();
         error_log('VoyagerRestful: Failed to parse response XML: ' . $error->message . ", response:\n" . $xmlResponse);
         $logger->log('Failed to parse response XML: ' . $error->message . ", response:\n" . $xmlResponse, PEAR_LOG_ERR);
         $this->debugLog('Failed to parse response XML: ' . $error->message . ", response:\n" . $xmlResponse);
         return false;
     }
     if ($mode == 'GET') {
         $this->getCache[$urlParams] = $simpleXML;
     }
     return $simpleXML;
 }
示例#2
0
 /**
  * Get data and output in JSON
  *
  * @return void
  * @access public
  */
 public function getRSIStatuses()
 {
     //<SFX server>:<port>/<sfx_instance>/cgi/core/rsi/rsi.cgi
     global $configArray;
     if (!isset($configArray['OpenURL']['url'])) {
         return $this->output(array(), JSON::STATUS_OK);
     }
     $sfxUrl = $configArray['OpenURL']['url'] . "/cgi/core/rsi/rsi.cgi";
     $metalib = new MetaLib();
     $indexEngine = SearchObjectFactory::initSearchObject()->getIndexEngine();
     $dom = new DOMDocument('1.0', 'UTF-8');
     // ID REQUEST
     $idReq = $dom->createElement('IDENTIFIER_REQUEST', '');
     $idReq->setAttribute("VERSION", "1.0");
     $idReq->setAttribute("xsi:noNamespaceSchemaLocation", "ISSNRequest.xsd");
     $idReq->setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
     $dom->appendChild($idReq);
     // Cache values and status in an array
     $rsiResults = array();
     $validRequest = false;
     foreach ($_REQUEST['id'] as $id) {
         if (strncmp($id, 'metalib.', 8) == 0) {
             if (!($record = $metalib->getRecord($id))) {
                 $this->output('Record does not exist', JSON::STATUS_ERROR);
                 return;
             }
             $values = array('isbn' => !empty($record['ISBN']) ? $record['ISBN'][0] : '', 'issn' => !empty($record['ISSN']) ? $record['ISSN'][0] : '', 'year' => !empty($record['PublicationDate']) ? $record['PublicationDate'][0] : '', 'volume' => !empty($record['Volume']) ? $record['Volume'] : '', 'issue' => !empty($record['Issue']) ? $record['Issue'] : '', 'institute' => isset($configArray['OpenURL']['institute']) ? $configArray['OpenURL']['institute'] : '');
         } else {
             if (!($record = $indexEngine->getRecord($id))) {
                 $this->output('Record does not exist', JSON::STATUS_ERROR);
                 return;
             }
             $recordDriver = RecordDriverFactory::initRecordDriver($record);
             $values = $recordDriver->getRSIValues($recordDriver);
         }
         $result = array('id' => $id, 'status' => 'noInformation');
         // Ignore the record if mandatory elements are not available
         if (empty($values['issn']) && empty($values['isbn'])) {
             // Mark this result invalid so it can be skipped when processing results
             $result['invalid'] = true;
             $rsiResults[] = $result;
             continue;
         }
         $rsiResults[] = $result;
         $validRequest = true;
         // ID REQUEST ITEM
         $idReqItem = $dom->createElement('IDENTIFIER_REQUEST_ITEM', '');
         $idReq->appendChild($idReqItem);
         // ID
         if (!empty($values['issn'])) {
             $identifier = $dom->createElement('IDENTIFIER', 'issn:' . $values['issn']);
             $idReqItem->appendChild($identifier);
         }
         if (!empty($values['isbn'])) {
             $identifier = $dom->createElement('IDENTIFIER', 'isbn:' . $values['isbn']);
             $idReqItem->appendChild($identifier);
         }
         // Optional elements
         if ($values['year']) {
             $year = $dom->createElement('YEAR', $values['year']);
             $idReqItem->appendChild($year);
         }
         if ($values['volume']) {
             $volume = $dom->createElement('VOLUME', $values['volume']);
             $idReqItem->appendChild($volume);
         }
         if ($values['issue']) {
             $issue = $dom->createElement('ISSUE', $values['issue']);
             $idReqItem->appendChild($issue);
         }
         if ($values['institute']) {
             $institute = $dom->createElement('INSTITUTE_NAME', $values['institute']);
             $idReqItem->appendChild($institute);
         }
     }
     if (!$validRequest) {
         return $this->output(array(), JSON::STATUS_OK);
     }
     $xml = $dom->saveXML();
     $req = new Proxy_Request($sfxUrl, array('saveBody' => true));
     $req->setMethod(HTTP_REQUEST_METHOD_POST);
     $req->addPostData('request_xml', $xml);
     $req->sendRequest();
     $code = $req->getResponseCode();
     if ($code != 200) {
         $this->output("SFX RSI request failed ({$code})", JSON::STATUS_ERROR);
         return;
     }
     $dom->loadXML($req->getResponseBody());
     $items = $dom->getElementsByTagName('IDENTIFIER_RESPONSE_ITEM');
     $position = -1;
     foreach ($items as $item) {
         $requests = $dom->getElementsByTagName('IDENTIFIER_REQUEST_ITEM');
         $request = $requests->item(0);
         $position++;
         // Bypass invalid ID's and stop if at the end of list.
         while (isset($rsiResults[$position]['invalid'])) {
             ++$position;
         }
         if (!isset($rsiResults[$position])) {
             break;
         }
         $result = $item->getElementsByTagName('RESULT')->item(0)->nodeValue;
         if ($result == 'not found') {
             $rsiResults[$position]['status'] = 'noFullText';
         } elseif ($result == 'maybe') {
             $rsiResults[$position]['status'] = 'maybeFullText';
         } else {
             foreach ($item->getElementsByTagName('AVAILABLE_SERVICES') as $service) {
                 if ($service->nodeValue == 'getFullTxt') {
                     $peerReviewed = false;
                     foreach ($item->getElementsByTagName('PEER_REVIEWED') as $peer) {
                         if ($peer->nodeValue == 'YES') {
                             $peerReviewed = true;
                             break;
                         }
                     }
                     $rsiResults[$position]['status'] = $peerReviewed ? 'peerReviewedFullText' : 'fullText';
                     break;
                 }
             }
         }
     }
     $results = array();
     foreach ($rsiResults as $result) {
         $results[] = array('id' => $result['id'], 'status' => $result['status']);
     }
     return $this->output($results, JSON::STATUS_OK);
 }
示例#3
0
 /**
  * Send a request to the SIRSI side API script and returns the response.
  *
  * @param array $params Associative array of query parameters to send.
  *
  * @return string
  */
 protected function querySirsi($params)
 {
     // make sure null parameters are sent as empty strings instead or else the
     // driver.pl may choke on null parameter values
     foreach ($params as $key => $value) {
         if ($value == null) {
             $params[$key] = '';
         }
     }
     $url = $this->url;
     if (empty($url)) {
         $url = $this->host;
         if ($this->port) {
             $url = "http://" . $url . ":" . $this->port . "/" . $this->search_prog;
         } else {
             $url = "http://" . $url . "/" . $this->search_prog;
         }
     }
     $httpClient = new Proxy_Request();
     // use HTTP POST so parameters like user id and PIN are NOT logged by web
     // servers
     $httpClient->setMethod(HTTP_REQUEST_METHOD_POST);
     $httpClient->setURL($url);
     $httpClient->setBody(http_build_query($params));
     $result = $httpClient->sendRequest();
     if (!PEAR::isError($result)) {
         // Even if we get a response, make sure it's a 'good' one.
         if ($httpClient->getResponseCode() != 200) {
             PEAR::raiseError("Error response code received from {$url}");
         }
     } else {
         PEAR::raiseError($result);
     }
     // get the response data
     $response = $httpClient->getResponseBody();
     return rtrim($response);
 }
示例#4
0
 /**
  * Constructor
  *
  * Sets up the SOAP Client
  *
  * @param	  string	$host			 The URL for the local Solr Server
  * @param   string  $index      The name of the index
  * @access	public
  */
 function __construct($host, $index = '')
 {
     global $configArray;
     global $timer;
     // Set a default Solr index if none is provided to the constructor:
     if (empty($index)) {
         $index = isset($configArray['Index']['default_core']) ? $configArray['Index']['default_core'] : "biblio";
     }
     //Check for a more specific searchspecs file
     global $serverName;
     if (file_exists("../../sites/{$serverName}/conf/searchspecs.yaml")) {
         // Return the file path (note that all ini files are in the conf/ directory)
         $this->searchSpecsFile = "../../sites/{$serverName}/conf/searchspecs.yaml";
     } elseif (file_exists("../../sites/default/conf/searchspecs.yaml")) {
         // Return the file path (note that all ini files are in the conf/ directory)
         $this->searchSpecsFile = "../../sites/default/conf/searchspecs.yaml";
     }
     $this->host = $host . '/' . $index;
     /** @var Memcache $memCache */
     global $memCache;
     if ($memCache) {
         $pingDone = $memCache->get('solr_ping');
     } else {
         $pingDone = false;
     }
     if ($pingDone == false) {
         // Test to see solr is online
         $test_url = $this->host . "/admin/ping";
         $test_client = new Proxy_Request();
         $test_client->setMethod(HTTP_REQUEST_METHOD_GET);
         $test_client->setURL($test_url);
         $result = $test_client->sendRequest();
         if (!PEAR_Singleton::isError($result)) {
             // Even if we get a response, make sure it's a 'good' one.
             if ($test_client->getResponseCode() != 200) {
                 PEAR_Singleton::raiseError('Solr index is offline.');
             }
         } else {
             PEAR_Singleton::raiseError($result);
         }
         if ($memCache) {
             $memCache->set('solr_ping', true, 0, $configArray['Caching']['solr_ping']);
         }
         $timer->logTime('Ping Solr instance');
     }
     // If we're still processing then solr is online
     $this->client = new Proxy_Request(null, array('useBrackets' => false));
     // Read in preferred boolean behavior:
     $searchSettings = getExtraConfigArray('searches');
     if (isset($searchSettings['General']['case_sensitive_bools'])) {
         $this->caseSensitiveBooleans = $searchSettings['General']['case_sensitive_bools'];
     }
     if (isset($searchSettings['General']['case_sensitive_ranges'])) {
         $this->_caseSensitiveRanges = $searchSettings['General']['case_sensitive_ranges'];
     }
     // Turn on highlighting if the user has requested highlighting or snippet
     // functionality:
     $highlight = !isset($searchSettings['General']['highlighting']) ? false : $searchSettings['General']['highlighting'];
     $snippet = !isset($searchSettings['General']['snippets']) ? false : $searchSettings['General']['snippets'];
     if ($highlight || $snippet) {
         $this->_highlight = true;
     }
     // Deal with field-stripping shard settings:
     if (isset($searchSettings['StripFields']) && is_array($searchSettings['StripFields'])) {
         $this->_solrShardsFieldsToStrip = $searchSettings['StripFields'];
     }
     // Deal with search spec cache setting:
     if (isset($searchSettings['Cache']['type'])) {
         $this->_specCache = $searchSettings['Cache']['type'];
     }
     if (isset($_SESSION['shards'])) {
         $this->_loadShards($_SESSION['shards']);
     }
     $timer->logTime('Finish Solr Initialization');
 }
示例#5
0
 /**
  * Call MetaLib X-Server
  *
  * @param string $operation X-Server operation
  * @param array  $params    URL Parameters
  *
  * @return mixed simpleXMLElement | PEAR_Error
  * @access protected
  */
 protected function callXServer($operation, $params)
 {
     $request = new Proxy_Request($this->config['General']['url'], array('method' => 'POST'));
     // Declare UTF-8 encoding so that SimpleXML won't encode characters.
     $xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?><x_server_request/>');
     $op = $xml->addChild($operation);
     $this->paramsToXml($op, $params);
     $request->addPostdata('xml', $xml->asXML());
     if ($this->debug) {
         echo "<!-- {$operation}\n";
         if ($operation != 'login_request') {
             echo $xml->asXML();
         }
         echo "-->\n";
     }
     $result = $request->sendRequest();
     if (PEAR::isError($result)) {
         return $result;
     }
     if ($this->debug) {
         echo "<!-- \n";
         echo $request->getResponseBody();
         echo "-->\n\n\n";
     }
     if ($request->getResponseCode() >= 400) {
         return new PEAR_Error("HTTP Request failed: " . $request->getResponseCode());
     }
     $xml = simplexml_load_string($request->getResponseBody());
     $errors = $xml->xpath('//local_error | //global_error');
     if (!empty($errors)) {
         if ($errors[0]->error_code == 6026) {
             return new PEAR_Error('Search timed out');
         }
         return new PEAR_Error($errors[0]->asXML());
     }
     return $xml;
 }
示例#6
0
 /**
  * Constructor
  *
  * @param string|string[] $hosts The URL(s) for the local Solr Server
  * @param string          $index The core to use on the specified server
  *
  * @access public
  */
 public function __construct($hosts, $index = '')
 {
     global $configArray;
     // Set a default Solr index if none is provided to the constructor:
     if (empty($index)) {
         $this->core = isset($configArray['Index']['default_core']) ? $configArray['Index']['default_core'] : "biblio";
     } else {
         $this->core = $index;
     }
     if (!is_array($hosts)) {
         $hosts = array($hosts);
     }
     for ($i = 0; $i < count($hosts); $i++) {
         $host = $hosts[$i];
         $this->host = $host . '/' . $this->core;
         // Test to see solr is online
         $test_url = $this->host . "/admin/ping";
         $test_client = new Proxy_Request();
         $test_client->setMethod(HTTP_REQUEST_METHOD_GET);
         $test_client->setURL($test_url);
         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
         $result = $test_client->sendRequest();
         PEAR::popErrorHandling();
         if (!PEAR::isError($result)) {
             // Even if we get a response, make sure it's a 'good' one.
             if ($test_client->getResponseCode() != 200) {
                 if ($i == count($hosts) - 1) {
                     // Last possible host, raise an error
                     PEAR::raiseError('Solr index is offline.');
                 }
                 continue;
             }
         } else {
             if ($i == count($hosts) - 1) {
                 // Last possible host, raise an error
                 PEAR::raiseError($result);
             }
             continue;
         }
         // Test was successful, use this host
         break;
     }
     // If we're still processing then solr is online
     $this->client = new Proxy_Request(null, array('useBrackets' => false));
     // Read in preferred boolean/range behavior:
     $searchSettings = getExtraConfigArray('searches');
     if (isset($searchSettings['General']['case_sensitive_bools'])) {
         $this->_caseSensitiveBooleans = $searchSettings['General']['case_sensitive_bools'];
     }
     if (isset($searchSettings['General']['case_sensitive_ranges'])) {
         $this->_caseSensitiveRanges = $searchSettings['General']['case_sensitive_ranges'];
     }
     // Turn on highlighting if the user has requested highlighting or snippet
     // functionality:
     $highlight = !isset($searchSettings['General']['highlighting']) ? false : $searchSettings['General']['highlighting'];
     $snippet = !isset($searchSettings['General']['snippets']) ? false : $searchSettings['General']['snippets'];
     if ($highlight || $snippet) {
         $this->_highlight = true;
     }
     // Deal with field-stripping shard settings:
     if (isset($searchSettings['StripFields']) && is_array($searchSettings['StripFields'])) {
         $this->_solrShardsFieldsToStrip = $searchSettings['StripFields'];
     }
     // Deal with search spec cache setting:
     if (isset($searchSettings['Cache']['type'])) {
         $this->_specCache = $searchSettings['Cache']['type'];
     }
     // Deal with session-based shard settings (but only in the main Solr class;
     // shard settings will mess up subclasses):
     if (isset($_SESSION['shards']) && get_class($this) == 'Solr') {
         $shards = array();
         foreach ($_SESSION['shards'] as $current) {
             if (isset($configArray['IndexShards'][$current])) {
                 $shards[$current] = $configArray['IndexShards'][$current];
             }
         }
         // if only one shard is used, take its URL as SOLR-Host-URL
         if (count($shards) === 1) {
             $shardsKeys = array_keys($shards);
             $this->host = 'http://' . $shards[$shardsKeys[0]];
         }
         // always set the shards -- even if only one is selected, we may
         // need to filter fields and facets:
         $this->setShards($shards);
     }
     // Merged records
     if (isset($searchSettings['Records']['merged_records'])) {
         $this->_mergedRecords = $searchSettings['Records']['merged_records'];
         $this->_recordSources = isset($searchSettings['Records']['sources']) ? $searchSettings['Records']['sources'] : '';
         $this->setPreferredRecordSource();
     }
     // Hide component parts?
     if (isset($searchSettings['General']['hide_component_parts'])) {
         $this->_hideComponentParts = $searchSettings['General']['hide_component_parts'];
     }
     // Use UNICODE normalization?
     if (isset($configArray['Index']['unicode_normalization_form'])) {
         $this->_unicodeNormalizationForm = $configArray['Index']['unicode_normalization_form'];
     }
 }
示例#7
0
 /**
  * Make an OAI-PMH request.  Die if there is an error; return a SimpleXML object
  * on success.
  *
  * @param string $verb   OAI-PMH verb to execute.
  * @param array  $params GET parameters for ListRecords method.
  *
  * @return object        SimpleXML-formatted response.
  * @access private
  */
 private function _sendRequest($verb, $params = array())
 {
     // Debug:
     if ($this->_verbose) {
         echo "Sending request: verb = {$verb}, params = ";
         print_r($params);
     }
     // Set up retry loop:
     while (true) {
         // Set up the request:
         $request = new Proxy_Request();
         $request->setMethod(HTTP_REQUEST_METHOD_GET);
         $request->setURL($this->_baseURL);
         // Load request parameters:
         $request->addQueryString('verb', $verb);
         foreach ($params as $key => $value) {
             $request->addQueryString($key, $value);
         }
         // Perform request and die on error:
         $result = $request->sendRequest();
         if (PEAR::isError($result)) {
             die($result->getMessage() . "\n");
         }
         // Check for 503 response.
         if ($request->getResponseCode() == 503) {
             $delay = $request->getResponseHeader('Retry-After');
             if ($delay > 0) {
                 if ($this->_verbose) {
                     echo "Received 503 response; waiting {$delay} seconds...\n";
                 }
                 sleep($delay);
             }
         } else {
             // If we didn't get a 503, we can leave the retry loop:
             break;
         }
     }
     // If we got this far, there was no error -- send back response.
     $response = $request->getResponseBody();
     return $this->_processResponse($response);
 }