You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
561 lines
20 KiB
561 lines
20 KiB
<?php |
|
|
|
|
|
/** |
|
* EBSCO Response class |
|
* |
|
* PHP version 5 |
|
* |
|
* |
|
* Copyright [2014] [EBSCO Information Systems] |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
require_once 'sanitizer.class.php'; |
|
|
|
|
|
/** |
|
* EBSCOResponse class |
|
*/ |
|
class EBSCOResponse |
|
{ |
|
|
|
/** |
|
* A SimpleXml object |
|
* @global object |
|
*/ |
|
private $response; |
|
|
|
|
|
/** |
|
* Constructor |
|
* |
|
* Sets up the EBSCO Response |
|
* |
|
* @param none |
|
* |
|
* @access public |
|
*/ |
|
public function __construct($response) |
|
{ |
|
$this->response = $response; |
|
} |
|
|
|
|
|
/** |
|
* Returns the XML as an associative array of data |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access public |
|
*/ |
|
public function result() |
|
{ |
|
if (!empty($this->response->AuthToken)) { |
|
return $this->buildAuthenticationToken(); |
|
} else if (!empty($this->response->SessionToken)) { |
|
return (string) $this->response->SessionToken; |
|
} else if (!empty($this->response->SearchResult)) { |
|
return $this->buildSearch(); |
|
} else if(!empty($this->response->Record)) { |
|
return $this->buildRetrieve(); |
|
} else if(!empty($this->response->AvailableSearchCriteria)) { |
|
return $this->buildInfo(); |
|
} else { // Should not happen, it may be an exception |
|
return $this->response; |
|
} |
|
} |
|
|
|
|
|
/** |
|
* Parse the SimpleXml object when an AuthenticationToken API call was executed |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access private |
|
*/ |
|
private function buildAuthenticationToken() |
|
{ |
|
$token = (string) $this->response->AuthToken; |
|
$timeout = (integer) $this->response->AuthTimeout; |
|
|
|
$result = array( |
|
'authenticationToken' => $token, |
|
'authenticationTimeout' => $timeout |
|
); |
|
|
|
return $result; |
|
} |
|
|
|
/** |
|
* Parse a SimpleXml object and |
|
* return it as an associative array |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access private |
|
*/ |
|
private function buildSearch() |
|
{ |
|
$hits = (integer) $this->response->SearchResult->Statistics->TotalHits; |
|
$searchTime = (integer) $this->response->SearchResult->Statistics->TotalSearchTime / 1000; |
|
$records = array(); |
|
$facets = array(); |
|
if ($hits > 0) { |
|
$records = $this->buildRecords(); |
|
$facets = $this->buildFacets(); |
|
} |
|
|
|
$results = array( |
|
'recordCount' => $hits, |
|
'searchTime' => $searchTime, |
|
'numFound' => $hits, |
|
'start' => 0, |
|
'documents' => $records, |
|
'facets' => $facets |
|
); |
|
|
|
return $results; |
|
} |
|
|
|
|
|
/** |
|
* Parse a SimpleXml object and |
|
* return it as an associative array |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access private |
|
*/ |
|
private function buildRecords() |
|
{ |
|
$results = array(); |
|
|
|
$records = $this->response->SearchResult->Data->Records->Record; |
|
foreach ($records as $record) { |
|
$result = array(); |
|
|
|
$result['ResultId'] = $record->ResultId ? (integer) $record->ResultId : ''; |
|
$result['DbId'] = $record->Header->DbId ? (string) $record->Header->DbId : ''; |
|
$result['DbLabel'] = $record->Header->DbLabel ? (string) $record->Header->DbLabel : ''; |
|
$result['An'] = $record->Header->An ? (string) $record->Header->An : ''; |
|
$result['PubType'] = $record->Header->PubType ? (string) $record->Header->PubType : ''; |
|
$result['AccessLevel'] = $record->Header->AccessLevel ? (string) $record->Header->AccessLevel : ''; |
|
$result['id'] = $result['An'] . '|' . $result['DbId']; |
|
$result['PLink'] = $record->PLink ? (string) $record->PLink : ''; |
|
if (!empty($record->ImageInfo->CoverArt)) { |
|
foreach ($record->ImageInfo->CoverArt as $image) { |
|
$size = (string) $image->Size; |
|
$target = (string) $image->Target; |
|
$result['ImageInfo'][$size] = $target; |
|
} |
|
} else { |
|
$result['ImageInfo'] = ''; |
|
} |
|
|
|
if ($record->FullText) { |
|
$availability = (integer) $record->FullText->Text->Availability == 1; |
|
$links = array(); |
|
//RF 2012-12-18 |
|
if (isset($record->FullText->Links)) |
|
{ |
|
foreach ($record->FullText->Links->Link as $link) { |
|
$type = (string) $link->Type; |
|
$url = (string) $link->Url; |
|
// If we have an empty url when type is pdflink then just return something so |
|
// that the UI check for empty string will pass. |
|
$url = empty($url) && $type == 'pdflink' ? 'http://content.ebscohost.com' : $url; |
|
$links[$type] = $url; |
|
} |
|
} |
|
$result['FullText'] = array( |
|
'Availability' => $availability, |
|
'Links' => $links |
|
); |
|
} |
|
|
|
if ($record->CustomLinks) { |
|
$result['CustomLinks'] = array(); |
|
foreach ($record->CustomLinks->CustomLink as $customLink) { |
|
$category = $customLink->Category ? (string) $customLink->Category : ''; |
|
$icon = $customLink->Icon ? (string) $customLink->Icon : ''; |
|
$mouseOverText = $customLink->MouseOverText ? (string) $customLink->MouseOverText : ''; |
|
$name = $customLink->Name ? (string) $customLink->Name : ''; |
|
$text = $customLink->Text ? (string) $customLink->Text : ''; |
|
$url = $customLink->Url ? (string) $customLink->Url : ''; |
|
$result['CustomLinks'][] = array( |
|
'Category' => $category, |
|
'Icon' => $icon, |
|
'MouseOverText' => $mouseOverText, |
|
'Name' => $name, |
|
'Text' => $text, |
|
'Url' => $url |
|
); |
|
} |
|
} |
|
|
|
if($record->Items) { |
|
$result['Items'] = array(); |
|
foreach ($record->Items->Item as $item) { |
|
$name = $item->Name ? (string) $item->Name : ''; |
|
$label = $item->Label ? (string) $item->Label : ''; |
|
$group = $item->Group ? (string) $item->Group : ''; |
|
$data = $item->Data ? (string) $item->Data : ''; |
|
$result['Items'][$name] = array( |
|
'Name' => $name, |
|
'Label' => $label, |
|
'Group' => $group, |
|
'Data' => $this->toHTML($data, $group) |
|
); |
|
} |
|
} |
|
|
|
$results[] = $result; |
|
} |
|
|
|
return $results; |
|
} |
|
|
|
|
|
/** |
|
* Parse a SimpleXml object and |
|
* return it as an associative array |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access private |
|
*/ |
|
private function buildFacets() |
|
{ |
|
$results = array(); |
|
|
|
$facets = $this->response->SearchResult->AvailableFacets->AvailableFacet; |
|
foreach ($facets as $facet) { |
|
$values = array(); |
|
foreach ($facet->AvailableFacetValues->AvailableFacetValue as $value) { |
|
$this_value = (string) $value->Value; |
|
$this_value = str_replace(array('\(','\)'), array('(', ')'), $this_value); |
|
$this_action = (string) $value->AddAction; |
|
$this_action = str_replace(array('\(','\)'), array('(', ')'), $this_action); |
|
$values[] = array( |
|
'Value' => $this_value, |
|
'Action' => $this_action, |
|
'Count' => (string) $value->Count |
|
); |
|
} |
|
$id = (string) $facet->Id; |
|
$label = (string) $facet->Label; |
|
if (!empty($label)) { |
|
$results[] = array( |
|
'Id' => $id, |
|
'Label' => $label, |
|
'Values' => $values, |
|
'isApplied' => false |
|
); |
|
} |
|
} |
|
|
|
return $results; |
|
} |
|
|
|
|
|
/** |
|
* Parse a SimpleXml object and |
|
* return it as an associative array |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access private |
|
*/ |
|
private function buildInfo() |
|
{ |
|
// Sort options |
|
$elements = $this->response->AvailableSearchCriteria->AvailableSorts->AvailableSort; |
|
$sort = array(); |
|
foreach ($elements as $element) { |
|
$sort[] = array( |
|
'Id' => (string) $element->Id, |
|
'Label' => (string) $element->Label, |
|
'Action' => (string) $element->AddAction |
|
); |
|
} |
|
|
|
// Search fields |
|
$elements = $this->response->AvailableSearchCriteria->AvailableSearchFields->AvailableSearchField; |
|
$tags = array(); |
|
foreach ($elements as $element) { |
|
$tags[] = array( |
|
'Label' => (string) $element->Label, |
|
'Code' => (string) $element->FieldCode |
|
); |
|
} |
|
|
|
// Expanders |
|
$elements = $this->response->AvailableSearchCriteria->AvailableExpanders->AvailableExpander; |
|
$expanders = array(); |
|
foreach ($elements as $element) { |
|
$expanders[] = array( |
|
'Id' => (string) $element->Id, |
|
'Label' => (string) $element->Label, |
|
'Action' => (string) $element->AddAction, |
|
'selected' => false // Added because of the checkboxes |
|
); |
|
} |
|
|
|
// Limiters |
|
$elements = $this->response->AvailableSearchCriteria->AvailableLimiters->AvailableLimiter; |
|
$limiters = array(); |
|
$values = array(); |
|
foreach ($elements as $element) { |
|
if ($element->LimiterValues) { |
|
$items = $element->LimiterValues->LimiterValue; |
|
foreach($items as $item) { |
|
$values[] = array( |
|
'Value' => (string) $item->Value, |
|
'Action' => (string) $item->AddAction, |
|
'selected' => false // Added because of the checkboxes |
|
); |
|
} |
|
} |
|
$limiters[] = array( |
|
'Id' => (string) $element->Id, |
|
'Label' => (string) $element->Label, |
|
'Action' => (string) $element->AddAction, |
|
'Type' => (string) $element->Type, |
|
'Values' => $values, |
|
'selected' => false |
|
); |
|
} |
|
|
|
$result = array( |
|
'sort' => $sort, |
|
'tags' => $tags, |
|
'expanders' => $expanders, |
|
'limiters' => $limiters |
|
); |
|
|
|
return $result; |
|
} |
|
|
|
|
|
/** |
|
* Parse a SimpleXml object and |
|
* return it as an associative array |
|
* |
|
* @param none |
|
* |
|
* @return array An associative array of data |
|
* @access private |
|
*/ |
|
private function buildRetrieve() |
|
{ |
|
$record = $this->response->Record; |
|
if ($record) { |
|
$record = $record[0]; // there is only one record |
|
} |
|
|
|
$result = array(); |
|
$result['DbId'] = $record->Header->DbId ? (string) $record->Header->DbId : ''; |
|
$result['DbLabel'] = $record->Header->DbLabel ? (string) $record->Header->DbLabel : ''; |
|
$result['An'] = $record->Header->An ? (string) $record->Header->An : ''; |
|
$result['id'] = $result['An'] . '|' . $result['DbId']; |
|
$result['PubType'] = $record->Header->PubType ? (string) $record->Header->PubType : ''; |
|
$result['AccessLevel'] = $record->Header->AccessLevel ? (string) $record->Header->AccessLevel : ''; |
|
$result['PLink'] = $record->PLink ? (string) $record->PLink : ''; |
|
if (!empty($record->ImageInfo->CoverArt)) { |
|
foreach ($record->ImageInfo->CoverArt as $image) { |
|
$size = (string) $image->Size; |
|
$target = (string) $image->Target; |
|
$result['ImageInfo'][$size] = $target; |
|
} |
|
} else { |
|
$result['ImageInfo'] = ''; |
|
} |
|
if ($record->FullText) { |
|
$availability = (integer) ($record->FullText->Text->Availability) == 1; |
|
$links = array(); |
|
foreach ($record->FullText->Links->Link as $link) { |
|
$type = (string) $link->Type; |
|
$url = (string) $link->Url; |
|
// If we have an empty url when type is pdflink then just return something so |
|
// that the UI check for empty string will pass. |
|
$url = empty($url) && $type == 'pdflink' ? 'http://content.ebscohost.com' : $url; |
|
$links[$type] = $url; |
|
} |
|
$value = $this->toHTML($record->FullText->Text->Value); |
|
$result['FullText'] = array( |
|
'Availability' => $availability, |
|
'Links' => $links, |
|
'Value' => $value |
|
); |
|
} |
|
|
|
if ($record->CustomLinks) { |
|
$result['CustomLinks'] = array(); |
|
foreach ($record->CustomLinks->CustomLink as $customLink) { |
|
$category = $customLink->Category ? (string) $customLink->Category : ''; |
|
$icon = $customLink->Icon ? (string) $customLink->Icon : ''; |
|
$mouseOverText = $customLink->MouseOverText ? (string) $customLink->MouseOverText : ''; |
|
$name = $customLink->Name ? (string) $customLink->Name : ''; |
|
$text = $customLink->Text ? (string) $customLink->Text : ''; |
|
$url = $customLink->Url ? (string) $customLink->Url : ''; |
|
$result['CustomLinks'][] = array( |
|
'Category' => $category, |
|
'Icon' => $icon, |
|
'MouseOverText' => $mouseOverText, |
|
'Name' => $name, |
|
'Text' => $text, |
|
'Url' => $url |
|
); |
|
} |
|
} |
|
|
|
if($record->Items) { |
|
$result['Items'] = array(); |
|
foreach ($record->Items->Item as $item) { |
|
$name = $item->Name ? (string) $item->Name : ''; |
|
$label = $item->Label ? (string) $item->Label : ''; |
|
$group = $item->Group ? (string) $item->Group : ''; |
|
$data = $item->Data ? (string) $item->Data : ''; |
|
$result['Items'][$name] = array( |
|
'Name' => $name, |
|
'Label' => $label, |
|
'Group' => $group, |
|
'Data' => $this->toHTML($data, $group) |
|
); |
|
} |
|
} |
|
|
|
return $result; |
|
} |
|
|
|
|
|
/** |
|
* Parse a SimpleXml element and |
|
* return it's inner XML as an HTML string |
|
* |
|
* @param SimpleXml $element A SimpleXml DOM |
|
* |
|
* @return string The HTML string |
|
* @access protected |
|
*/ |
|
private function toHTML($data, $group = null) |
|
{ |
|
// Any group can be added here, but we only use Au (Author) |
|
// Other groups, not present here, won't be transformed to HTML links |
|
$allowed_searchlink_groups = array('au'); |
|
|
|
// Map xml tags to the HTML tags |
|
// This is just a small list, the total number of xml tags is far more greater |
|
$xml_to_html_tags = array( |
|
'<jsection' => '<section', |
|
'</jsection' => '</section', |
|
'<highlight' => '<span class="highlight"', |
|
'<highligh' => '<span class="highlight"', // Temporary bug fix |
|
'</highlight>' => '</span>', // Temporary bug fix |
|
'</highligh' => '</span>', |
|
'<text' => '<div', |
|
'</text' => '</div', |
|
'<title' => '<h2', |
|
'</title' => '</h2', |
|
'<anid' => '<p', |
|
'</anid' => '</p', |
|
'<aug' => '<p class="aug"', |
|
'</aug' => '</p', |
|
'<hd' => '<h3', |
|
'</hd' => '</h3', |
|
'<linebr' => '<br', |
|
'</linebr' => '', |
|
'<olist' => '<ol', |
|
'</olist' => '</ol', |
|
'<reflink' => '<a', |
|
'</reflink' => '</a', |
|
'<blist' => '<p class="blist"', |
|
'</blist' => '</p', |
|
'<bibl' => '<a', |
|
'</bibl' => '</a', |
|
'<bibtext' => '<span', |
|
'</bibtext' => '</span', |
|
'<ref' => '<div class="ref"', |
|
'</ref' => '</div', |
|
'<ulink' => '<a', |
|
'</ulink' => '</a', |
|
'<superscript' => '<sup', |
|
'</superscript'=> '</sup', |
|
'<relatesTo' => '<sup', |
|
'</relatesTo' => '</sup' |
|
); |
|
|
|
// Map xml types to Search types used by the UI |
|
$xml_to_search_types = array( |
|
'au' => 'Author', |
|
'su' => 'Subject' |
|
); |
|
|
|
// The XML data is XML escaped, let's unescape html entities (e.g. < => <) |
|
$data = html_entity_decode($data); |
|
|
|
// Start parsing the xml data |
|
if (!empty($data)) { |
|
// Replace the XML tags with HTML tags |
|
$search = array_keys($xml_to_html_tags); |
|
$replace = array_values($xml_to_html_tags); |
|
$data = str_replace($search, $replace, $data); |
|
|
|
// Temporary : fix unclosed tags |
|
$data = preg_replace('/<\/highlight/', '</span>', $data); |
|
$data = preg_replace('/<\/span>>/', '</span>', $data); |
|
$data = preg_replace('/<\/searchLink/', '</searchLink>', $data); |
|
$data = preg_replace('/<\/searchLink>>/', '</searchLink>', $data); |
|
|
|
// Parse searchLinks |
|
if (!empty($group)) { |
|
$group = strtolower($group); |
|
if (in_array($group, $allowed_searchlink_groups)) { |
|
$type = $xml_to_search_types[$group]; |
|
$path = url('ebsco/results', array('query' => array('type' => $type))); |
|
$link_xml = '/<searchLink fieldCode="([^\"]*)" term="%22([^\"]*)%22">/'; |
|
$link_html = "<a href=\"{$path}&lookfor=$2\">"; |
|
$data = preg_replace($link_xml, $link_html, $data); |
|
$data = str_replace('</searchLink>', '</a>', $data); |
|
} |
|
} |
|
|
|
// Replace the rest of searchLinks with simple spans |
|
$link_xml = '/<searchLink fieldCode="([^\"]*)" term="%22([^\"]*)%22">/'; |
|
$link_html = '<span>'; |
|
$data = preg_replace($link_xml, $link_html, $data); |
|
$data = str_replace('</searchLink>', '</span>', $data); |
|
|
|
// Parse bibliography (anchors and links) |
|
$data = preg_replace('/<a idref="([^\"]*)"/', '<a href="#$1"', $data); |
|
$data = preg_replace('/<a id="([^\"]*)" idref="([^\"]*)" type="([^\"]*)"/', '<a id="$1" href="#$2"', $data); |
|
} |
|
|
|
$sanitizer = new HTML_Sanitizer; |
|
$data = $sanitizer->sanitize($data); |
|
|
|
return $data; |
|
} |
|
|
|
|
|
} |
|
|
|
?>
|