Exemplo n.º 1
0
 /**
  * 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;
 }
Exemplo n.º 2
0
 /**
  * Parse the primo response
  *
  * @param string $response
  * @return ResultSet
  */
 public function parseResponse($response)
 {
     // load it
     $xml = Parser::convertToDOMDocument($response);
     // header("Content-type:text/xml"); echo $xml->saveXML(); exit;
     // check for errors
     $error = $xml->getElementsByTagName("ERROR")->item(0);
     if ($error != "") {
         throw new \Exception($error->getAttribute("MESSAGE"));
     }
     // set-up the result set
     $result_set = new Search\ResultSet($this->config);
     // total
     $docset = $xml->getElementsByTagName("DOCSET")->item(0);
     if ($docset == null) {
         throw new \Exception("Could not determine total number of records");
     }
     $total = $docset->getAttribute("TOTALHITS");
     $result_set->total = $total;
     // extract records
     foreach ($this->extractRecords($xml) as $xerxes_record) {
         $result_set->addRecord($xerxes_record);
     }
     // facets
     $facets = $this->extractFacets($xml);
     $result_set->setFacets($facets);
     return $result_set;
 }
Exemplo n.º 3
0
 public function loadXML($doc)
 {
     $id = null;
     $format = null;
     $score = null;
     $xml_data = "";
     foreach ($doc->str as $str) {
         // marc record
         if ((string) $str["name"] == 'fullrecord') {
             $marc = trim((string) $str);
             // marc-xml
             if (substr($marc, 0, 5) == '<?xml') {
                 $xml_data = $marc;
             } else {
                 $marc = preg_replace('/#31;/', "", $marc);
                 $marc = preg_replace('/#30;/', "", $marc);
                 $marc_file = new \File_MARC($marc, \File_MARC::SOURCE_STRING);
                 $marc_record = $marc_file->next();
                 $xml_data = $marc_record->toXML();
             }
         } elseif ((string) $str["name"] == 'id') {
             $id = (string) $str;
         }
     }
     // format
     foreach ($doc->arr as $arr) {
         if ($arr["name"] == "format") {
             $format = (string) $arr->str;
         }
     }
     // score
     foreach ($doc->float as $float) {
         if ($float["name"] == "score") {
             $score = (string) $float;
         }
     }
     // load marc data
     $this->marc = new MarcRecord();
     $this->marc->loadXML($xml_data);
     // save for later
     $this->document = Parser::convertToDOMDocument($doc);
     $this->serialized = $doc->asXml();
     // process it
     $this->map();
     $this->cleanup();
     // add non-marc data
     $this->setRecordID($id);
     $this->setScore($score);
     $this->format()->setInternalFormat($format);
     $this->format()->setPublicFormat($format);
     // custom mappings
     if (class_exists('Local\\Model\\Solr\\Record')) {
         $local = new \Local\Model\Solr\Record();
         $local->map($this, $this->marc);
     }
 }
Exemplo n.º 4
0
 /**
  * Serialize to XML
  * 
  * @return array
  */
 public function toXML()
 {
     $xml = Parser::convertToDOMDocument('<holding />');
     foreach ($this->data as $name => $value) {
         $line = $xml->createElement('data', Parser::escapeXml($value));
         $line->setAttribute('key', $name);
         $xml->documentElement->appendChild($line);
     }
     return $xml;
 }
Exemplo n.º 5
0
 public function toXML()
 {
     $xml = Parser::convertToDOMDocument("<lti />");
     $this->appendElement($xml, "id", $this->getID());
     $this->appendElement($xml, "instructor", $this->isInstructor());
     foreach ($this->request->get_parameters() as $id => $value) {
         $this->appendElement($xml, $id, $value);
     }
     return $xml;
 }
Exemplo n.º 6
0
 /**
  * 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;
 }
Exemplo n.º 7
0
 public function toXML()
 {
     $xml = Parser::convertToDOMDocument("<category />");
     $xml->documentElement->setAttribute("name", $this->name);
     $xml->documentElement->setAttribute("normalized", $this->normalized);
     foreach ($this->subcategories as $subcategory) {
         $import = $xml->importNode($subcategory->toXML()->documentElement, true);
         $xml->documentElement->appendChild($import);
     }
     return $xml;
 }
Exemplo n.º 8
0
 public function toXML()
 {
     $xml = Parser::convertToDOMDocument("<subcategory />");
     $xml->documentElement->setAttribute("name", $this->name);
     $xml->documentElement->setAttribute("sequence", $this->sequence);
     $xml->documentElement->setAttribute("id", $this->databases_id);
     foreach ($this->databases as $database) {
         $import = $xml->importNode($database->toXML()->documentElement, true);
         $xml->documentElement->appendChild($import);
     }
     return $xml;
 }
Exemplo n.º 9
0
 /**
  * Add a database to the local knowledgebase
  *
  * @param Database $objDatabase
  */
 public function addDatabase(Database $objDatabase)
 {
     // load our data into xml object
     $xml = simplexml_load_string($objDatabase->data);
     // these fields have boolen values in metalib
     $boolean_fields = array("proxy", "searchable", "guest_access", "subscription", "sfx_suppress", "new_resource_expiry");
     // normalize boolean values
     foreach ($xml->children() as $child) {
         $name = (string) $child->getName();
         $value = (string) $child;
         if (in_array($name, $boolean_fields)) {
             $xml->{$name} = $this->convertMetalibBool($value);
         }
     }
     // remove empty nodes
     $dom = Parser::convertToDOMDocument($xml->asXML());
     $xmlPath = new \DOMXPath($dom);
     $xmlNullNodes = $xmlPath->query('//*[not(node())]');
     foreach ($xmlNullNodes as $node) {
         $node->parentNode->removeChild($node);
     }
     $objDatabase->data = $dom->saveXML();
     // add the main database entries
     $this->doSimpleInsert("xerxes_databases", $objDatabase);
     // now also extract searchable fields so we can populate the search table
     // get fields from config
     foreach ($this->searchable_fields as $search_field) {
         $search_field = trim($search_field);
         foreach ($xml->{$search_field} as $field) {
             $searchable_terms = array();
             foreach (explode(" ", (string) $field) as $term) {
                 // only numbers and letters please
                 $term = preg_replace('/[^a-zA-Z0-9]/', '', $term);
                 $term = strtolower($term);
                 // anything over 50 chars is likley a URL or something
                 if (strlen($term) > 50) {
                     continue;
                 }
                 array_push($searchable_terms, $term);
             }
             // remove duplicate terms
             $searchable_terms = array_unique($searchable_terms);
             // insert em
             $strSQL = "INSERT INTO xerxes_databases_search ( database_id, field, term ) " . "VALUES ( :metalib_id, :field, :term )";
             foreach ($searchable_terms as $unique_term) {
                 $this->insert($strSQL, array(":metalib_id" => $objDatabase->metalib_id, ":field" => $search_field, ":term" => $unique_term));
             }
         }
     }
 }
Exemplo n.º 10
0
 /**
  * Load data from XML
  */
 public function loadXML($xml)
 {
     $this->document = Parser::convertToDOMDocument($xml);
     $this->xpath = new \DOMXPath($this->document);
     // test to see what profile the context object is using
     // set namespace accordingly
     if ($this->document->getElementsByTagNameNS("info:ofi/fmt:xml:xsd:book", "book")->item(0) != null) {
         $this->xpath->registerNamespace("rft", "info:ofi/fmt:xml:xsd:book");
     } elseif ($this->document->getElementsByTagNameNS("info:ofi/fmt:xml:xsd:dissertation", "dissertation")->item(0) != null) {
         $this->xpath->registerNamespace("rft", "info:ofi/fmt:xml:xsd:dissertation");
     } elseif ($this->document->getElementsByTagNameNS("info:ofi/fmt:xml:xsd", "journal")->item(0) != null) {
         $this->xpath->registerNamespace("rft", "info:ofi/fmt:xml:xsd");
     } else {
         $this->xpath->registerNamespace("rft", "info:ofi/fmt:xml:xsd:journal");
     }
     $this->map();
     $this->cleanup();
 }
Exemplo n.º 11
0
 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->setOptions(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 = Parser::convertToDOMDocument($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;
 }
Exemplo n.º 12
0
 /**
  * Load from MARC-XML source
  *
  * @param string|DOMNode|DOMDocument $node
  */
 public function loadXML($node = null)
 {
     if ($node != null) {
         // make sure we have a DOMDocument
         $this->document = Parser::convertToDOMDocument($node);
         // extract the three data types
         $leader = $this->document->getElementsByTagName("leader");
         $control_fields = $this->document->getElementsByTagName("controlfield");
         $data_fields = $this->document->getElementsByTagName("datafield");
         // leader
         $this->leader = new Leader($leader->item(0));
         // control fields
         foreach ($control_fields as $control_field) {
             $controlfield = new ControlField($control_field);
             array_push($this->_controlfields, $controlfield);
         }
         // data fields
         foreach ($data_fields as $data_field) {
             $datafield = new DataField($data_field);
             array_push($this->_datafields, $datafield);
         }
     }
 }
Exemplo n.º 13
0
 public function getOriginalXML($bolString = false)
 {
     // convert original (JSON-based) array to xml
     $this->document = Parser::convertToDOMDocument('<original />');
     Parser::addToXML($this->document, 'record', $this->original_array);
     return parent::getOriginalXML($bolString);
 }
Exemplo n.º 14
0
 /**
  * Creates a sorting page element
  *
  * @param string $sort			current sort
  *
  * @return DOMDocument 			sort navigation
  */
 public function sortDisplay($sort)
 {
     $sort_options = $this->config->sortOptions();
     if (count($sort_options) == 0) {
         return null;
     }
     $xml = Parser::convertToDOMDocument("<sort_display />");
     $x = 1;
     foreach ($sort_options as $key => $value) {
         if ($key == $sort) {
             $here = $xml->createElement("option", $value);
             $here->setAttribute("active", "true");
             $xml->documentElement->appendChild($here);
         } else {
             $params = $this->sortLinkParams();
             $params["sort"] = $key;
             $here = $xml->createElement("option", $value);
             $here->setAttribute("active", "false");
             $here->setAttribute("link", $this->request->url_for($params));
             $xml->documentElement->appendChild($here);
         }
         $x++;
     }
     return $xml;
 }
Exemplo n.º 15
0
 /**
  * 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);
 }
Exemplo n.º 16
0
 /**
  * Parse the ebsco response
  *
  * @param string $response
  * @return ResultSet
  */
 public function parseResponse($response)
 {
     // load it in
     $xml = Parser::convertToDOMDocument($response);
     // catch a non-xml response
     if ($xml->documentElement == null) {
         throw new \Exception("Could not connect to Ebsco search server");
     }
     // check for fatal error
     if ($xml->documentElement->nodeName == 'Fault') {
         $message = $xml->getElementsByTagName('Message')->item(0);
         if ($message != null) {
             if ($message->nodeValue == "The following parameter(s) have incorrect values: Field query: Greater than 0") {
                 throw new \Exception('Ebsco search error: your search query cannot be empty');
             }
             // need to get a fresh set of databases
             if (strstr($message->nodeValue, 'User does not have access rights to database')) {
                 throw new DatabaseException($message->nodeValue);
             }
             throw new \Exception('Ebsco server error: ' . $message->nodeValue);
         }
     }
     // 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 && $this->query->start > $this->query->max) {
         // but let's not get crazy here
         if ($this->deincrementing <= 8) {
             $this->deincrementing++;
             $new_start = $this->query->start - $this->query->max;
             $this->query->start = $new_start;
             return $this->doSearch($this->query);
         }
     }
     // we've reached the end prematurely, so set this to the end
     $check_end = $this->query->start + $check;
     if ($check < $this->query->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);
     /*
     
     $facets_id = 'facets' . $query->getHash();
     
     // cached clusters
     
     $cached_facets = $this->cache->get($facets_id);
     
     if ( $cached_facets instanceof Facets )
     {
     	$results->setFacets($cached_facets);
     }
     else
     {
     	$facets = $this->extractFacets($xml);
     	$this->cache->set($facets_id, $facets);
     	$results->setFacets($facets);
     }
     */
     return $results;
 }
Exemplo n.º 17
0
 /**
  * Search and retieve records
  *
  * @throws Exception for diagnostic errors
  * 
  * @param mixed $query				the query in CQL format
  * @param int $iStartRecord			[optional] start record to begin with, default 1
  * @param int $iMaxiumumRecords		[optional] maximum records to return, default 10
  * @param string $strSort			[optional] index to sort records on
  * 
  * @return DOMDocument				SRU results response
  */
 public function searchRetrieve($query, $iStartRecord = 1, $iMaxiumumRecords = 10, $strSort = null)
 {
     // append any limits set earlier
     $this->query = $query . " " . $this->limits;
     // construct the request to the server
     $this->url = $this->base . "?wskey=" . $this->key;
     $this->url .= "&version=1.1";
     $this->url .= "&operation=searchRetrieve";
     $this->url .= "&query=" . urlencode($this->query);
     $this->url .= "&startRecord=" . $iStartRecord;
     $this->url .= "&maximumRecords=" . $iMaxiumumRecords;
     $this->url .= "&recordSchema=marcxml";
     $this->url .= "&servicelevel=" . $this->service;
     // workset grouping
     if ($this->frbr == false) {
         $this->url .= "&frbrGrouping=off";
     }
     // sort order
     if ($strSort != "") {
         $this->url .= "&sortKeys=" . $strSort;
     }
     // get the response from the server
     $results = $this->fetchResults($this->url);
     $objXml = Parser::convertToDOMDocument($results);
     $objXPath = new \DOMXPath($objXml);
     $objXPath->registerNameSpace("zs", "http://www.loc.gov/zing/srw/");
     // check for diagnostic errors
     $objDiagnostics = $objXPath->query("zs:diagnostics");
     if ($objDiagnostics->length > 0) {
         $strError = "";
         $diagnostics = simplexml_import_dom($objDiagnostics->item(0));
         foreach ($diagnostics->diagnostic as $diagnostic) {
             $strError .= $diagnostic->message;
             if ((string) $diagnostic->details != "") {
                 $strError .= ": " . $diagnostic->details;
             }
         }
         throw new \Exception($strError);
     }
     // extract total hits
     $objTotal = $objXPath->query("zs:numberOfRecords")->item(0);
     if ($objTotal != null) {
         $this->total = (int) $objTotal->nodeValue;
     }
     return $objXml;
 }
Exemplo n.º 18
0
 /**
  * Return values as XML
  * 
  * @param null|array|\ArrayAccess Values to use during rendering
  */
 public function toXML($vars)
 {
     $xml = Parser::convertToDOMDocument('<xerxes />');
     foreach ($vars as $id => $object) {
         Parser::addToXML($xml, $id, $object);
     }
     return $xml;
 }
Exemplo n.º 19
0
 /**
  * Serialize to XML
  */
 public function toXML()
 {
     $xml = new \SimpleXMLElement('<link />');
     if ($this->isFullText()) {
         $xml->addAttribute("type", "full");
         $xml->addAttribute("format", $this->getType());
     } else {
         $xml->addAttribute("type", $this->getType());
     }
     $xml->display = $this->getDisplay();
     $xml->url = $this->getURL();
     return Parser::convertToDOMDocument($xml);
 }
Exemplo n.º 20
0
 /**
  * Load a MARC-XML document from string or object
  *
  * @param string|DOMNode|DOMDocument $xml
  */
 public function loadXML($xml)
 {
     $xml = Parser::convertToDOMDocument($xml);
     $this->parse($xml);
 }
Exemplo n.º 21
0
 /**
  * Serialize to XML
  *
  * @return DOMDocument
  */
 public function toXML()
 {
     // data is already in xml, we just use this opportunity to
     // enhance it with a few bits of data we don't already have
     ### display name for group restrictions
     if (count($this->simplexml()->group_restriction) > 0) {
         foreach ($this->simplexml()->group_restriction as $group_restriction) {
             $group_restriction->addAttribute("display_name", $this->config()->getGroupDisplayName((string) $group_restriction));
         }
     }
     ### split note fields into separate entries per language
     $multilingual = $this->config()->getConfig("db_description_multilingual", false, "");
     // XML object
     // build a list of configured description languages
     $db_languages_code = array();
     $db_languages_order = array();
     if ($multilingual != "") {
         $order = 0;
         foreach ($multilingual->language as $language) {
             $order++;
             $code = NULL;
             foreach ($language->attributes() as $name => $val) {
                 if ($name == "code") {
                     $code = (string) $val;
                 }
             }
             $db_languages_order[$code] = $order;
             $db_languages_code[$order] = $code;
         }
     }
     $notes = array("description", "search_hints");
     foreach ($notes as $note_field_name) {
         $node_queue = array();
         // nodes to add when done looping to prevent looping over nodes added inside the loop
         foreach ($this->simplexml()->{$note_field_name} as $note_field_xml) {
             $note_field = (string) $note_field_xml;
             $pos = strpos($note_field, '######');
             if ($multilingual == false || $pos === false) {
                 $note_field = str_replace('######', '\\n\\n\\n', $note_field);
             } else {
                 $descriptions = explode('######', $note_field);
                 $i = 1;
                 foreach ($descriptions as $description) {
                     $description = $this->embedNoteField($description);
                     $node_queue[] = array('note_field_name' => $note_field_name, 'description' => $description, 'code' => $db_languages_code[$i++]);
                 }
             }
             $note_field = $this->embedNoteField($note_field);
             $this->simplexml()->{$note_field_name} = $note_field;
             $this->simplexml()->{$note_field_name}->addAttribute('lang', 'ALL');
         }
         foreach ($node_queue as $node) {
             $descNode = $this->simplexml()->addChild($node['note_field_name'], $node['description']);
             $descNode->addAttribute('lang', $node['code']);
         }
     }
     // convert to DOMDocument
     $objDom = Parser::convertToDOMDocument($this->simplexml()->asXML());
     // add database id
     $objDatabase = $objDom->documentElement;
     $objDatabase->setAttribute("database_id", $this->database_id);
     // is the particular user allowed to search this?
     $objElement = $objDom->createElement("searchable_by_user", $this->searchable_by_user);
     // @todo need to change this
     $objDatabase->appendChild($objElement);
     return $objDom;
 }
Exemplo n.º 22
0
 /**
  * Fetch the data from Metalib and check for errors
  *
  * @param string $url		url of the request
  */
 private function getResponse($url, $timeout = null, $retry = 0)
 {
     // fetch the data
     $this->client->setUri($url);
     $this->client->setConfig(array('timeout' => $timeout));
     $response = $this->client->send();
     if ($response->isClientError() || $response->getBody() == "") {
         throw new \Exception("Cannot process search at this time.");
     }
     // load into xml
     $doc = Parser::convertToDOMDocument($response->getBody());
     // no response?
     if ($doc->documentElement == null) {
         throw new \Exception("cannot connect to metalib server");
     }
     // error in response
     if ($doc->getElementsByTagName("error_code") != null) {
         // for easier handling
         $xml = simplexml_import_dom($doc->documentElement);
         foreach ($xml->xpath("//global_error|//local_error") as $error) {
             $error_code = (int) $error->error_code;
             $error_text = (string) $error->error_text;
             // now examine them
             // metalib session has timed out!
             if ($error_code == 0151) {
                 // this particular metalib error message is confusing to end-users, so make it more clear
                 $error_text = "The Metalib session has expired";
                 // also try to re-up the session in the event metalib was restarted or something
                 if ($retry == 0) {
                     $this->session = $this->getSession();
                     return $this->getResponse($url, $timeout, 1);
                 }
             }
             // these are just warnings
             if ($error_code == 2114 || $error_code == 6039 || $error_code == 6033 || $error_code == 6034 || $error_code == 6023 || $error_code == 134 || $error_code == 6022) {
                 trigger_error("Metalib warning ({$error_code}): {$error_text}", E_USER_WARNING);
             } else {
                 throw new \Exception("Metalib exception ({$error_code}): {$error_text}");
             }
         }
     }
     return $doc;
 }
Exemplo n.º 23
0
 /**
  * Fetch record information
  *
  * @param string $id	bibliographic id
  */
 public function getHoldings($id)
 {
     $holdings = new Search\Holdings();
     // fetch holdings page from web service
     $url = $this->server . "GetHoldingsService?bibId={$id}";
     $content = $this->client->getUrl($url, 4);
     // load and parse it
     $xml = Parser::convertToDOMDocument($content);
     // header("Content-type: text/xml"); echo $xml->saveXML(); 	exit;
     $records = $xml->getElementsByTagName("mfhdRecord");
     foreach ($records as $record) {
         $item = new Search\Item();
         $item->id = $record->getAttribute("mfhdId");
         $item_count = (int) $record->getElementsByTagName("itemCount")->item(0)->nodeValue;
         // @todo what is this?
         foreach ($record->getElementsByTagName("datafield") as $datafield) {
             if ($datafield->getAttribute("tag") == "866") {
                 $datafield->textContent;
             }
         }
         if ($item_count == 0) {
             continue;
         }
         $unavailable = 0;
         foreach ($record->getElementsByTagName("itemData") as $itemData) {
             if ($itemData->getAttribute("name") == "statusCode") {
                 if ($itemData->nodeValue != 1) {
                     $unavailable++;
                 }
             }
         }
         // holding record
         if ($item_count > 1 && $unavailable > 0) {
             $holding = new Search\Holding();
             // item count summary
             $available = $item_count - $unavailable;
             $number_of_items = "{$item_count} items ({$available} available)";
             $holding->setProperty('Number of items', $number_of_items);
             $holdings->addHolding($holding);
             continue;
         }
         // locations
         $locations = array();
         foreach ($record->getElementsByTagName("itemLocation") as $location_node) {
             $location = "";
             $caption = "";
             $temp = false;
             foreach ($location_node->getElementsByTagName("itemLocationData") as $location_data) {
                 if ($location_data->getAttribute("name") == "tempLocation") {
                     if (!in_array($location_data->nodeValue, $this->ignore_locations)) {
                         $location = $location_data->nodeValue;
                     }
                 } elseif ($location_data->getAttribute("name") == "itemCaption") {
                     $caption = $location_data->nodeValue;
                 } elseif ($location_data->getAttribute("name") == "tmpLoc") {
                     $temp = true;
                 }
             }
             if ($location != "") {
                 // if this is the temp location, then previous one is the 'old' location
                 if ($temp == true) {
                     array_pop($locations);
                 }
                 $locations[$location] = $caption;
             }
         }
         // no locations, so skip it yo!
         if (count($locations) == 0) {
             continue;
         }
         // call number
         foreach ($record->getElementsByTagName("mfhdData") as $data) {
             if ($data->getAttribute("name") == "callNumber") {
                 $item->callnumber = $data->nodeValue;
             }
         }
         // status
         foreach ($record->getElementsByTagName("itemData") as $data) {
             if ($data->getAttribute("name") == "statusCode") {
                 $status = $data->nodeValue;
                 $public_status = $this->config->getPublicStatus($status);
                 if ($public_status != null) {
                     $item->status = $public_status;
                     if ($item_count > count($locations)) {
                         $item->status .= " ({$item_count} items)";
                     }
                 }
                 if ($status == 1) {
                     $item->availability = true;
                 } else {
                     $item->availability = false;
                 }
             } elseif ($data->getAttribute("name") == "statusDate") {
                 $date = $data->nodeValue;
                 $matches = array();
                 if (preg_match('/([0-9]{4})-([0-9]{2})-([0-9]{2})/', $date, $matches)) {
                     $item->duedate = $matches[2] . "-" . $matches[3] . "-" . $matches[1];
                     $item->status = str_replace('\\d', $item->duedate, $item->status);
                 }
             }
         }
         foreach ($locations as $item_location => $caption) {
             if ($caption != "") {
                 $item->location = "{$caption} shelved at {$item_location}";
             } else {
                 $item->location = $item_location;
             }
             $holdings->addItem($item);
         }
     }
     return $holdings;
 }
Exemplo n.º 24
0
 /**
  * Retrieve the MARC Record as MARC-XML
  * 
  * @return DOMDocument
  */
 public function getMarcXML()
 {
     if (!$this->document instanceof \DOMDocument) {
         // we've created this MARC record from our own objects
         // instead of a marc-xml source, so create marc-xml now
         $this->document = Parser::convertToDOMDocument('<record xmlns="' . $this->namespace . '" />');
         // leader
         if ($this->leader instanceof Leader) {
             $leader_xml = $this->document->createElementNS($this->namespace, "leader", $this->leader->value);
             $this->document->appendChild($leader_xml);
         }
         // control fields
         foreach ($this->controlfields() as $controlfield) {
             $controlfield_xml = $this->document->createElementNS($this->namespace, "controlfield", $controlfield->value);
             $controlfield_xml->setAttribute("tag", $controlfield->tag);
             $this->document->appendChild($controlfield_xml);
         }
         // data fields
         foreach ($this->datafield() as $datafield) {
             $datafield_xml = $this->document->createElementNS($this->namespace, "datafield");
             $datafield_xml->setAttribute("tag", $datafield->tag);
             $this->document->appendChild($datafield_xml);
             // subfields
             foreach ($datafield->subfield() as $subfield) {
                 $subfield_xml = $this->document->createElementNS($this->namespace, "subfield", $subfield->value);
                 $subfield_xml->setAttribute("code", $subfield->code);
                 $datafield_xml->appendChild($subfield_xml);
             }
         }
     }
     return $this->document;
 }
Exemplo n.º 25
0
 /**
  * Creates a sorting page element
  *
  * @param string $sort  current sort
  *
  * @return DOMDocument  sort navigation
  */
 public function sortDisplay($sort)
 {
     $sort_options = $this->config->sortOptions();
     if (count($sort_options) == 0) {
         return null;
     }
     $xml = Parser::convertToDOMDocument("<sort_display />");
     $x = 1;
     foreach ($sort_options as $id) {
         $here = $xml->createElement('option');
         $here->setAttribute('id', $id);
         if ($id == $sort) {
             $here->setAttribute('active', 'true');
         } else {
             $params = $this->sortLinkParams();
             $params['sort'] = $id;
             $here->setAttribute('active', 'false');
             $here->setAttribute('link', $this->request->url_for($params));
         }
         $xml->documentElement->appendChild($here);
         $x++;
     }
     return $xml;
 }
Exemplo n.º 26
0
 /**
  * Extracts the MARC data from the HTML response and converts it to MARC-XML
  *
  * @param string $marc	marc data as string
  * @return DOMDocument		marc-xml document
  */
 protected function extractMarc($response)
 {
     $xml = Parser::convertToDOMDocument("<record xmlns=\"http://www.loc.gov/MARC21/slim\" />");
     $marc = "";
     // marc data as text
     $arrTags = array();
     // array to hold each MARC tag
     if (!stristr($response, "<pre>")) {
         // didn't find a record
         return $xml;
     }
     // parse out MARC data
     $marc = Parser::removeLeft($response, "<pre>");
     $marc = Parser::removeRight($marc, "</pre>");
     // remove break-tabs for easier parsing
     $marc = str_replace(" \n       ", " ", $marc);
     $marc = str_replace("\n       ", " ", $marc);
     $marc = trim($marc);
     // assign the marc values to the array based on Unix LF as delimiter
     $arrTags = explode("\n", $marc);
     foreach ($arrTags as $strTag) {
         // assign tag # and identifiers
         $strTagNumber = substr($strTag, 0, 3);
         $strId1 = substr($strTag, 4, 1);
         $strId2 = substr($strTag, 5, 1);
         // assign data and clean it up
         $data = substr($strTag, 7);
         // only convert all data to utf8 if told to do so,
         // but always do it to the leader, since it has mangled chars
         if ($this->convert_to_utf8 == true || $strTagNumber == "LEA") {
             if (function_exists("mb_convert_encoding")) {
                 $data = mb_convert_encoding($data, "UTF-8");
             } else {
                 $data = utf8_encode($data);
             }
         }
         $data = Parser::escapeXml($data);
         $data = trim($data);
         if ($strTagNumber == "LEA") {
             // leader
             $objLeader = $xml->createElementNS($this->marc_ns, "leader", $data);
             $xml->documentElement->appendChild($objLeader);
         } elseif ($strTagNumber == "REC") {
             // Pseudo-MARC "REC" data field to store the INNOPAC
             // bibliographic record number in subfield a.
             $objRecNum = $xml->createElementNS($this->marc_ns, "datafield");
             $objRecNum->setAttribute("tag", "REC");
             $objRecNum->setAttribute("ind1", ' ');
             $objRecNum->setAttribute("ind2", ' ');
             $objRecNumSub = $xml->createElementNS($this->marc_ns, "subfield", strtolower($data));
             $objRecNumSub->setAttribute("code", 'a');
             $objRecNum->appendChild($objRecNumSub);
             $xml->documentElement->appendChild($objRecNum);
         } elseif ((int) $strTagNumber <= 8) {
             // control fields
             $objControlField = $xml->createElementNS($this->marc_ns, "controlfield", $data);
             $objControlField->setAttribute("tag", $strTagNumber);
             $xml->documentElement->appendChild($objControlField);
         } else {
             // data fields
             $objDataField = $xml->createElementNS($this->marc_ns, "datafield");
             $objDataField->setAttribute("tag", $strTagNumber);
             $objDataField->setAttribute("ind1", $strId1);
             $objDataField->setAttribute("ind2", $strId2);
             // if first character is not a pipe symbol, then this is the default |a subfield
             // so make that explicit for the array
             if (substr($data, 0, 1) != "|") {
                 $data = "|a " . $data;
             }
             // split the subfield data on the pipe and add them in using the first
             // character after the delimiter as the subfield code
             $arrSubFields = explode("|", $data);
             foreach ($arrSubFields as $strSubField) {
                 if ($strSubField != "") {
                     $code = substr($strSubField, 0, 1);
                     $data = trim(substr($strSubField, 1));
                     // check for a url, in which case we need to ensure there are no spaces;
                     // which can happen on the wrap of the data in the marc display
                     if (strlen($data) > 4) {
                         if (substr($data, 0, 4) == "http") {
                             $data = str_replace(" ", "", $data);
                         }
                     }
                     $objSubField = $xml->createElementNS($this->marc_ns, "subfield", $data);
                     $objSubField->setAttribute("code", $code);
                     $objDataField->appendChild($objSubField);
                 }
             }
             $xml->documentElement->appendChild($objDataField);
         }
     }
     return $xml;
 }
Exemplo n.º 27
0
 /**
  * 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_selected, $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_selected != "") {
         $databases = array($database_selected);
     } else {
         // see if any supplied as facet limit
         foreach ($search->getLimits(true) as $limit) {
             if ($limit->field == "database") {
                 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 = Parser::convertToDOMDocument($response);
     // catch a non-xml response
     if ($xml->documentElement == null) {
         throw new \Exception("Could not connect to Ebsco search server");
     }
     // check for fatal error
     if ($xml->documentElement->nodeName == 'Fault') {
         $message = $xml->getElementsByTagName('Message')->item(0);
         if ($message != null) {
             throw new \Exception('Ebsco server error: ' . $message->nodeValue);
         }
     }
     // 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($search, $database_selected, $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;
 }
Exemplo n.º 28
0
 /**
  * Load, map, and clean-up record data from XML
  * 
  * @param mixed $xml		XML as DOM, SimpleXML or string
  */
 public function loadXML($xml)
 {
     $this->document = Parser::convertToDOMDocument($xml);
     $this->map();
     $this->cleanup();
 }
Exemplo n.º 29
0
 /**
  * Add reviews from Good Reads
  */
 public function addReviews()
 {
     $xerxes_record = $this->getXerxesRecord();
     $isbn = $xerxes_record->getISBN();
     $key = $this->registry->getConfig("GOOD_READS_API_KEY", false);
     if ($key != null) {
         $url = "http://www.goodreads.com/book/isbn?isbn={$isbn}&key={$key}";
         $data = Parser::request($url, 5);
         if ($data != "") {
             $xml = Parser::convertToDOMDocument($data);
             $this->reviews = $xml;
         }
     }
 }