Browse Source

Drupal module for EDS

roblib
Rui Francisco 11 years ago
parent
commit
85066e6622
  1. BIN
      Drupal module Setup.docx
  2. 431
      ebsco/css/ebsco.css
  3. 8
      ebsco/ebsco.info
  4. 1036
      ebsco/ebsco.module
  5. BIN
      ebsco/images/ajax_loading.gif
  6. BIN
      ebsco/images/sprites_32.png
  7. 186
      ebsco/js/ebsco.js
  8. 629
      ebsco/lib/EBSCOAPI.php
  9. 432
      ebsco/lib/EBSCOConnector.php
  10. 788
      ebsco/lib/EBSCODocument.php
  11. 398
      ebsco/lib/EBSCORecord.php
  12. 547
      ebsco/lib/EBSCOResponse.php
  13. 444
      ebsco/lib/sanitizer.class.php
  14. 44
      ebsco/templates/ebsco-advanced-search.tpl.php
  15. 27
      ebsco/templates/ebsco-basic-search.tpl.php
  16. 134
      ebsco/templates/ebsco-result.tpl.php
  17. 143
      ebsco/templates/ebsco-results.tpl.php
  18. 149
      ebsco/templates/ebsco-side-facets.tpl.php

BIN
Drupal module Setup.docx

Binary file not shown.

431
ebsco/css/ebsco.css

@ -0,0 +1,431 @@
/*
* The styles for EBSCO module
*/
@CHARSET "UTF-8";
/** General ***/
.floatleft {
float: left;
}
.floatright {
float: right;
}
.clear {
clear: both;
}
.offscreen {
display: none;
}
.spinner {
width: 16px;
height: 16px;
background: url("../images/ajax_loading.gif") no-repeat left top;
display: none;
}
.highlight {
font-weight: bold;
}
/** Search list ***/
.ebsco .result {
width: 650px;
}
.ebsco .record-number {
margin-right: 10px;
min-width: 10px;
}
.ebsco .span-2 {
width: auto;
max-width: 70px;
margin-right: 10px;
float: left;
}
.ebsco .span-9 {
float: none;
overflow: auto;
width: auto;
margin-right: 0;
}
.ebsco .pagination {
margin-bottom: 0;
padding: 0.2em
}
.ebsco p.submit {
padding: 10px 0;
}
.ebsco .jumpMenu {
max-width: 130px;
}
.ebsco ul.custom-links {
list-style-type: none;
margin: 0;
padding: 0;
}
.ebsco ul.custom-links li {
display: inline-block;
padding-left: 0;
padding-right: 10px;
margin-left: 10px;
border-right: 1px solid #CCCCCC;
}
.ebsco ul.custom-links li:first-child {
margin-left: 0;
}
.ebsco ul.custom-links li:last-child {
padding-right: 0;
border-right: 0 none;
}
/** Side facets **/
#block-ebsco-ebsco-facets h2 {
font-weight: bold;
}
#block-ebsco-ebsco-facets {
padding: 5px !important;
}
#block-ebsco-ebsco-facets dl {
margin: 5px 0;
padding: 0;
}
#block-ebsco-ebsco-facets dl dt {
font-size: 115%;
padding: 5px;
background-color: #eeeeee;
}
#block-ebsco-ebsco-facets dd {
font-weight: normal !important;
margin: 0;
padding: 5px !important;
border-bottom: 1px solid #dddddd;
}
#block-ebsco-ebsco-facets dd.submit input {
margin: 0;
}
#block-ebsco-ebsco-facets dl dd:last-child {
border-bottom: none;
}
#block-ebsco-ebsco-facets dd label {
font-weight: normal;
font-family: Arial;
padding: 0 3px;
}
#block-ebsco-ebsco-facets dd label {
display: inline;
}
#block-ebsco-ebsco-facets dl.expandable:hover {
cursor: pointer;
}
#block-ebsco-ebsco-facets dl.expandable:hover dt span {
color: #444444;
}
#block-ebsco-ebsco-facets .narrow-list.filters {
background-color: orange;
}
#block-ebsco-ebsco-facets .narrow-list.filters a {
color: white;
}
/** Detailed view ***/
.ebsco-record .toolbar {
border-bottom: 1px solid #EEEEEE;
margin-bottom: 1em;
min-height: 2em;
padding-left: 1em;
}
.ebsco-record.push-5 {
margin: 0;
}
.ebsco-record .span-13 {
min-width: 540px;
max-width: 690px;
width: auto;
float: left;
}
.ebsco-record .span-13 table {
margin-top: 0;
}
.ebsco-record .span-13 table tr td {
word-break: break-all;
}
.ebsco-record .span-4 {
max-width: 150px;
min-width: 80px;
width: auto;
margin: 0 0 0 10px;
text-align: center;
float: left;
}
.ebsco-record .external-links {
border: 1px solid #eeeeee;
list-style-type: none;
margin: 10px 0;
padding: 0;
}
.ebsco-record .external-links li {
display: inline-block;
padding-left: 0;
padding-right: 10px;
margin-left: 10px;
border-right: 1px solid #CCCCCC;
line-height: 32px;
margin: 5px;
}
.ebsco-record .external-links li:last-child {
border-right: 0 none;
}
.external-link img {
vertical-align: middle;
padding-right: 5px;
}
.top-login-message {
margin-top:10px;
width: 100%;
text-align: center;
}
.ebsco-record .record {
width: 100%;
padding: 0;
}
.ebsco-record .book-jacket {
max-width: 150px;
}
.ebsco-record .html {
background-color: white;
padding:10px 0;
border: 0;
}
/** Basic search form ***/
#ebsco-basic-search-form .form-item-lookfor,
#ebsco-basic-search-form .form-item-type {
display: inline !important;
}
#ebsco-basic-search-form #edit-links {
display: inline;
margin: 0;
padding: 0;
border: none 0;
position: static;
}
#ebsco-basic-search-form #edit-offscreen {
display: none;
}
#ebsco-basic-search-form .form-item-remember label {
font-weight: bold;
}
#ebsco-sort-form {
margin : 10px 0;
}
#ebsco-sort-form > div {
border-bottom: 1px solid #CCCCCC;
}
#ebsco-sort-form label,
#ebsco-sort-form .form-item {
display: inline-block !important;
}
#ebsco-sort-form .form-item:first-child {
float: right;
}
#ebsco-sort-form .form-item:last-child {
float: left;
}
/** Advanced search form ***/
.ebsco-advanced ._advanced-row {
border: 0 none;
padding: 0;
margin: 10px;
top: 5px;
}
.ebsco-advanced #edit-rows {
margin-bottom: 20px;
}
.ebsco-advanced ._advanced-row .fieldset-wrapper {
margin: 0 !important;
padding: 0;
}
.ebsco-advanced .form-item-group0-lookfor label {
display: inline-block;
text-align: right;
width: 100px;
}
.ebsco-advanced .form-type-radio label {
display: inline-block;
text-align: left;
width: 90%;
}
.ebsco-advanced #edit-add-row {
border: 0 none;
padding: 0;
margin: 10px;
top: 5px;
}
.ebsco-advanced #edit-add-row .fieldset-wrapper {
margin-top: 5px;
}
.ebsco-advanced #edit-links {
margin-bottom: 20px;
text-align: center;
}
.ebsco-advanced #edit-links .fieldset-wrapper {
margin-top: 10px;
}
.ebsco-advanced #edit-limiters {
width: 99%;
}
.ebsco-advanced #edit-modes {
width: 49%;
float: left;
}
.ebsco-advanced #edit-modes {
width: 49%;
float: left;
}
.ebsco-advanced #edit-expanders {
width: 49%;
float: right;
}
.ebsco-advanced #edit-limiters label {
font-weight: normal;
}
.ebsco-advanced #edit-limiters .form-type-select label {
display: block;
}
.ebsco-advanced #edit-limiters hr {
margin: 15px 0;
height: 1px;
background-color: #CCCCCC;
color: #CCCCCC;
border: 0 none;
}
.dateSlider {
width: 150px;
display: inline-block !important;
margin: 0 10px;
}
/** Icons ***/
.icon {
background: url("../images/sprites_32.png") no-repeat top left;
height: 32px;
line-height: 32px;
display: inline-block;
padding: 0 0 0 36px !important;
}
.icon.ebook {
background-position: 0 0;
}
.icon.html {
background-position: 0 -42px;
}
.icon.pdf {
background-position: 0 -84px;
}
.icon13 {
background: url("../images/sprites_32.png") no-repeat top left;
padding-left: 18px !important;
width: 13px;
height: 13px;
}
.icon13.collapsed {
background-position: 0 -126px;
}
.icon13.expanded {
background-position: 0 -149px;
}
.icon16 {
background: url("../images/sprites_32.png") no-repeat top left;
padding-left: 21px !important;
width: 16px;
height: 16px;
display: inline-block;
}
.icon16.tick {
background-position: 0 -171px;
}

8
ebsco/ebsco.info

@ -0,0 +1,8 @@
name = EBSCO Discovery Service
description = Full-text articles and eBooks from EBSCOhost Discovery Service
core = 7.x
configure = admin/config/search/ebsco
stylesheets[screen][] = css/ebsco.css
scripts[] = js/ebsco.js

1036
ebsco/ebsco.module

File diff suppressed because it is too large Load Diff

BIN
ebsco/images/ajax_loading.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
ebsco/images/sprites_32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

186
ebsco/js/ebsco.js

@ -0,0 +1,186 @@
/*
* The EBSCO module javascript
**/
(function ($) {
$(document).ready(function () {
//
var updatePublishDateSlider = function () {
var from = parseInt($('#DT1').val());
var min = 1000;
if (!from || from < min) {
from = min;
}
// and keep the max at 1 years from now
var max = (new Date()).getFullYear() + 1;
var to = max;
// update the slider with the new min/max/values
$('#ebsco-advanced-search-sliderDT1').slider('option', {
min: min, max: max, values: [from, to]
});
};
/*
* Self executing function
**/
var onLoad = function () {
// EBSCO/Search : Expand limiters
$('._more_limiters').live('click', function (event) {
$("#moreLimiters").hide();
$("#limitersHidden").removeClass("offscreen");
});
// Search : Collapse limiters
$('._less_limiters').live('click', function (event) {
$("#moreLimiters").show();
$("#limitersHidden").addClass("offscreen");
});
// EBSCO/Search : Collapse / expand facets
$('.expandable').live('click', function (event) {
var span = $(this).find('dt span'),
id = $(this).attr('id').replace('facet-','');
if (span.length > 0) {
if (span.hasClass('collapsed')) {
$('#narrowGroupHidden_' + id).show();
span.removeClass('collapsed');
span.addClass('expanded');
} else if (span.hasClass('expanded')) {
$('#narrowGroupHidden_' + id).hide();
span.removeClass('expanded');
span.addClass('collapsed');
}
} else if ($(this).attr('href')) {
var dl = $(this).parents('dl'),
id = dl.attr('id').replace('narrowGroupHidden_', ''),
span = $('#facet-' + id).find('dt span');
dl.hide();
span.removeClass('expanded');
span.addClass('collapsed');
}
});
// EBSCO/Search : Less facets
$('._less_facets').live('click', function (event) {
var id = $(this).attr('id').replace('less-facets-','');
var dl = $('#facet-' + id);
dl.trigger('click');
});
// Search : Ajax request the Record action
$('._record_link').live('click', function (event) {
var element = $(this);
var position = element.position();
event.preventDefault();
$('#spinner').show();
$("#spinner").offset({left:event.pageX - 18,top:event.pageY - 18});
$.get(element.attr('href'), function (data) {
$('#main').html(data);
$('#spinner').hide();
});
});
// Advanced Search : Add a new search term
$('._add_row').live('click', function (event) {
event.preventDefault();
var newSearch = $('#advanced-row-template').html();
var rows = $('._advanced-row');
if (rows) {
// Find the index of the next row
var index = rows.length - 1; // one row is the template itself, so don't count it
// Replace NN string with the index number
newSearch = newSearch.replace(/NN/g, index);
lastSearch = $('#edit-add-row');
lastSearch.before(newSearch);
}
});
// Advanced Search : Delete an advanced search row
$('._delete_row').live('click', function (event) {
event.preventDefault();
$(this).parents('._advanced-row').remove();
});
// Advanced Search : Reset the form fields to default values
$('.ebsco-advanced input[name="reset"]').live('click', function (event) {
event.preventDefault();
$('#ebsco-advanced-search-form').find('input, select').each(function (index) {
var type = this.type;
switch(type) {
case 'text':
$(this).val('');
break;
case 'checkbox':
$(this).attr('checked', '');
break;
case 'select-multiple':
$(this).children('option').each(function (index) {
$(this).attr('selected', '');
});
break;
case 'select-one':
$(this).children('option').each(function (index) {
$(this).attr('selected', '');
});
// for IE
$(this).children('option:first').attr('selected', 'selected');
break;
case 'radio':
$(this).attr('checked', '');
$(this).parent().siblings().first().children('input:first').attr('checked', 'checked');
break;
}
});
});
// Auto submit the seelct boxes with '_jump_menu' class
$('._jump_menu').live('change', function (event) {
var name = $(this).attr('id').replace('ebsco-', ''),
value = $(this).attr('value'),
url = $('#ebsco-sort-form').attr('action');
url += "&" + name + "=" + value;
window.location.href = url;
});
// Retain search filters checkbox functionality
$('#edit-remember').live('click', function (event) {
$("#ebsco-basic-search-form :input[type='checkbox'][name^='filter[']").attr('checked', $(this).attr('checked'));
});
// Advanced Search : handle 'Date Published from' limiter
// Create the UI slider (if slider function is defined)
if(typeof $("#ebsco-advanced-search-sliderDT1").slider == 'function') {
$('#ebsco-advanced-search-sliderDT1').slider({
range: true,
min: 0, max: 9999, values: [0, 9999],
slide: function (event, ui) {
$('#DT1').val(ui.values[0]);
if(ui.values[0] == 1000) {
$('#ebsco-advanced-search-limiterDT1').val('');
} else {
$('#ebsco-advanced-search-limiterDT1').val('addlimiter(DT1:' + ui.values[0] + '-1/2013-1)');
}
}
});
// initialize the slider with the original values
// in the text boxes
updatePublishDateSlider();
// when user enters values into the boxes
// the slider needs to be updated too
$('#DT1').change(function(){
updatePublishDateSlider();
});
}
}();
});
})(jQuery);

629
ebsco/lib/EBSCOAPI.php

@ -0,0 +1,629 @@
<?php
/**
* EBSCO EDS API class
*
* PHP version 5
*
*/
require_once 'EBSCOConnector.php';
require_once 'EBSCOResponse.php';
/**
* EBSCO API class
*/
class EBSCOAPI
{
/**
* The authentication token used for API transactions
* @global string
*/
private $authenticationToken;
/**
* The session token for API transactions
* @global string
*/
private $sessionToken;
/**
* The EBSCOConnector object used for API transactions
* @global object EBSCOConnector
*/
private $connector;
/**
* Configuration options
*/
private $config;
/**
* VuFind search types mapped to EBSCO search types
* used for urls in search results / detailed result
* @global array
*/
private static $search_tags = array(
'' => '',
'AllFields' => '',
'Abstract' => 'AB',
'Author' => 'AU',
'Source' => 'SO',
'Subject' => 'SU',
'Title' => 'TI'
);
/**
* EBSCO sort options
* @global array
*/
private static $sort_options = array(
'relevance',
'date',
'date2',
'source'
);
/**
* VuFind sort types mapped to EBSCO sort types
* used for urls in Search results / Detailed view
* @global array
*/
private static $mapped_sort_options = array(
'' => 'relevance',
'relevance' => 'relevance',
'subject' => 'date',
'date' => 'date2',
'date_asc' => 'date2',
'date_desc' => 'date',
'callnumber' => 'date',
'author' => 'author',
'title' => 'date'
);
/**
* Constructor
*
*
* @param array config
*
* @access public
*/
public function __construct($config)
{
$this->config = $config;
}
/**
* Setter / Getter for authentication token
*
* @param string The authentication token
*
* @return string or none
* @access public
*/
public function authenticationToken($token = null)
{
if (empty($token)) {
$token = $this->readSession('authenticationToken');
return !empty($token) ? $token : $this->authenticationToken;
} else {
$this->authenticationToken = $token;
$this->writeSession('authenticationToken', $token);
}
}
/**
* Setter / Getter for session token
*
* @param string The session token
*
* @return string or none
* @access public
*/
public function sessionToken($token = null)
{
if (empty($token)) {
$token = $this->readSession('sessionToken');
return !empty($token) ? $token : $this->sessionToken;
} else {
$this->sessionToken = $token;
$this->writeSession('sessionToken', $token);
}
}
/**
* Getter for isGuest
*
* @param string 'y' or 'n'
*
* @return string or none
* @access public
*/
public function isGuest($boolean = null)
{
if (empty($boolean)) {
return $this->readSession('isGuest');
} else {
$this->writeSession('isGuest', $boolean);
}
}
/**
* Create a new EBSCOConnector object or reuse an existing one
*
* @param none
*
* @return EBSCOConnector object
* @access public
*/
public function connector()
{
if (empty($this->connector)) {
$this->connector = new EBSCOConnector($this->config);
}
return $this->connector;
}
/**
* Create a new EBSCOResponse object
*
* @param object $response
*
* @return EBSCOResponse object
* @access public
*/
public function response($response)
{
$responseObj = new EBSCOResponse($response);
return $responseObj;
}
/**
* Request authentication and session tokens, then send the API request.
* Retry the request if authentication errors occur
*
* @param string $action The EBSCOConnector method name
* @param array $params The parameters of the HTTP request
* @param integer $attempts The number of retries
*
* @return object SimpleXml DOM or PEAR Error
* @access protected
*/
protected function request($action, $params = null, $attempts = 5)
{
$authenticationToken = $this->authenticationToken();
$sessionToken = $this->sessionToken();
// If authentication token is missing then the session token is missing too, so get both tokens
// If session token is missing then the authentication token may be invalid, so get both tokens
if (empty($authenticationToken) || empty($sessionToken)) {
$result = $this->apiAuthenticationAndSessionToken();
if ($this->isError($result)) {
// Any error should terminate the request immediately
// in order to prevent infinite recursion
return $result;
}
}
// Any change of the isGuest should request a new session
// (and don't terminate the current request if there was an error during the session request
// since it's not that important)
if ($this->isGuest() != $this->connector()->isGuest()) {
$this->apiSessionToken();
}
$headers = array(
'x-authenticationToken' => $this->authenticationToken(),
'x-sessionToken' => $this->sessionToken()
);
$response = call_user_func_array(array($this->connector(), "request{$action}"), array($params, $headers));
if ($this->isError($response)) {
// Retry the request if there were authentication errors
$code = $response->getCode();
switch ($code) {
// If authentication token is invalid then the session token is invalid too, so get both tokens
// If session token is invalid then the authentication token may be invalid too, so get both tokens
case EBSCOConnector::EDS_AUTH_TOKEN_INVALID:
$result = $this->apiAuthenticationToken();
if ($this->isError($result)) {
// Any error should terminate the request immediately
// in order to prevent infinite recursion
return $result;
}
if ($attempts > 0) {
$result = $this->request($action, $params, --$attempts);
}
break;
case EBSCOConnector::EDS_SESSION_TOKEN_INVALID:
$result = $this->apiAuthenticationAndSessionToken();
if ($this->isError($result)) {
// Any error should terminate the request immediately
// in order to prevent infinite recursion
return $result;
}
if ($attempts > 0) {
$result = $this->request($action, $params, --$attempts);
}
break;
default:
$result = $this->handleError($response);
break;
}
} else {
$result = $this->response($response)->result();
}
return $result;
}
/**
* Wrapper for authentication API call
*
* @param none
*
* @access public
*/
public function apiAuthenticationToken()
{
$response = $this->connector()->requestAuthenticationToken();
if ($this->isError($response)) {
return $response;
} else {
$result = $this->response($response)->result();
if (isset($result['authenticationToken'])) {
$this->authenticationToken($result['authenticationToken']);
return $result['authenticationToken'];
} else {
return new EBSCOException("No authentication token was found in the response.");
}
}
}
/**
* Wrapper for session API call
*
* @param none
*
* @access public
*/
public function apiSessionToken()
{
// Add authentication tokens to headers
$headers = array(
'x-authenticationToken' => $this->authenticationToken()
);
$response = $this->connector()->requestSessionToken($headers);
// Raise the exception so that any code running this method should exit immediately
if ($this->isError($response)) {
return $response;
} else {
$result = $this->response($response)->result();
if (is_string($result)) {
$this->sessionToken($result);
return $result;
} else {
return new EBSCOException("No session token was found in the response.");
}
}
}
/**
* Initialize the authentication and session tokens
*
* @param none
*
* @access public
*/
public function apiAuthenticationAndSessionToken()
{
$authenticationToken = $this->apiAuthenticationToken();
if ($this->isError($authenticationToken)) {
// An authentication error should terminate the request immediately
return $authenticationToken;
}
$sessionToken = $this->apiSessionToken();
if ($this->isError($sessionToken)) {
// A session error should terminate the request immediately
return $sessionToken;
}
// We don't have to return anything, both tokens can be accessed using the getters
return true;
}
/**
* Wrapper for search API call
*
* @param array $search The search terms
* @param array $filters The facet filters
* @param string $start The page to start with
* @param string $limit The number of records to return
* @param string $sortBy The value to be used by for sorting
* @param string $amount The amount of data to be returned
* @param string $mode The search mode
*
* @throws object PEAR Error
* @return array An array of query results
* @access public
*/
public function apiSearch($search, $filters,
$start = 1, $limit = 10, $sortBy = 'relevance', $amount = 'detailed', $mode = 'all'
) {
$query = array();
// Basic search
if(!empty($search['lookfor'])) {
$lookfor = $search['lookfor'];
$type = isset($search['index']) && !empty($search['index']) ? $search['index'] : 'AllFields';
// escape some characters from lookfor term
$term = str_replace(array(',', ':', '(', ')'), array('\,', '\:', '\(', '\)'), $lookfor);
// replace multiple consecutive empty spaces with one empty space
$term = preg_replace("/\s+/", ' ', $term);
// search terms
// Complex search term
if (preg_match('/(.*) (AND|OR) (.*)/i', $term)) {
$query['query'] = $term;
} else {
$tag = self::$search_tags[$type];
$op = 'AND';
$query_str = implode(',', array($op, $tag));
$query_str = implode(($tag ? ':' : ''), array($query_str, $term));
$query['query-1'] = $query_str;
}
// Advanced search
} else if(!empty($search['group'])) {
$counter = 1;
foreach ($search['group'] as $group) {
$type = $group['type'];
if (isset($group['lookfor'])) {
$term = $group['lookfor'];
$op = $group['bool'];
$tag = $type && isset(self::$search_tags[$type]) ? self::$search_tags[$type] : '';
// escape some characters from lookfor term
$term = str_replace(array(',', ':', '(', ')'), array('\,', '\:', '\(', '\)'), $term);
// replace multiple consecutive empty spaces with one empty space
$term = preg_replace("/\s+/", ' ', $term);
if (!empty($term)) {
$query_str = implode(',', array($op, $tag));
$query_str = implode(($tag ? ':' : ''), array($query_str, $term));
$query["query-$counter"] = $query_str;
$counter++;
}
}
}
// No search term, return an empty array
} else {
$results = array(
'recordCount' => 0,
'numFound' => 0,
'start' => 0,
'documents' => array(),
'facets' => array()
);
return $results;
}
// Add filters
$limiters = array(); $expanders = array(); $facets = array();
foreach ($filters as $filter) {
if (preg_match('/addlimiter/', $filter)) {
list($action, $str) = explode('(', $filter, 2);
$field_and_value = substr($str, 0, -1); // e.g. FT:y or GZ:Student Research, Projects and Publications
list($field, $value) = explode(':', $field_and_value, 2);
$limiters[$field][] = $value;
} else if (preg_match('/addexpander/', $filter)) {
list($action, $str) = explode('(', $filter, 2);
$field = substr($str, 0, -1); // expanders don't have value
$expanders[] = $field;
} else if (preg_match('/addfacetfilter/', $filter)) {
list($action, $str) = explode('(', $filter, 2);
$field_and_value = substr($str, 0, -1); // e.g. ZG:FRANCE
list($field, $value) = explode(':', $field_and_value, 2);
$facets[$field][] = $field_and_value;
}
}
if (!empty($limiters)) {
foreach($limiters as $field => $limiter) {
$query['limiter'][] = $field . ':' . implode(',', $limiter); // e.g. LA99:English,French,German
}
}
if (!empty($expanders)) {
$query['expander'] = implode(',', $expanders); // e.g. fulltext, thesaurus
}
if (!empty($facets)) {
$groupId = 1;
foreach($facets as $field => $facet) {
$query['facetfilter'][] = $groupId . ',' . implode(',', $facet); // e.g. 1,DE:Math,DE:History
$groupId += 1;
}
}
// Add the sort option
$sortBy = in_array($sortBy, self::$sort_options) ? $sortBy : self::$mapped_sort_options[$sortBy];
// Add the HTTP query params
$params = array(
// Specifies the sort. Valid options are:
// relevance, date, date2
// date = Date descending
// date2 = Date ascending
'sort' => $sortBy,
// Specifies the search mode. Valid options are:
// bool, any, all, smart
'searchmode' => $mode,
// Specifies the amount of data to return with the response
// Valid options are:
// title: Title only
// brief: Title + Source, Subjects
// detailed: Brief + full abstract
'view' => $amount,
/// Specifies whether or not to include facets
'includefacets' => 'y',
'resultsperpage' => $limit,
'pagenumber' => $start,
// Specifies whether or not to include highlighting in the search results
'highlight' => 'y'
);
$params = array_merge($params, $query);
$result = $this->request('Search', $params);
return $result;
}
/**
* Wrapper for retrieve API call
*
* @param array $an The accession number
* @param string $start The short database name
*
* @throws object PEAR Error
* @return array An associative array of data
* @access public
*/
public function apiRetrieve($an, $db)
{
// Add the HTTP query params
$params = array(
'an' => $an,
'dbid' => $db,
'highlight' => 'y'
);
$result = $this->request('Retrieve', $params);
return $result;
}
/**
* Wrapper for info API call
*
* @throws object PEAR Error
* @return array An associative array of data
* @access public
*/
public function apiInfo()
{
if ($result = $this->readSession('info')) {
return $result;
}
$result = $this->request('Info');
if(!$this->isError($result)) {
$this->writeSession('info', $result);
}
return $result;
}
/**
* Handle a PEAR_Error. Return :
* - if the error is critical : an associative array with the current error message
* - if the error is not critical : the error message
*
* @param Pear_Error $exception
*
* @return array or the Pear_Error exception
* @access protected
*/
private function handleError($error) {
$errorCode = $error->getCode();
switch($errorCode) {
// This kind of error was generated by user , so display it to user
case EBSCOConnector::EDS_INVALID_ARGUMENT_VALUE:
// Any other errors are system errors, don't display them to user
default:
$errorMessage = 'An error occurred when getting the data.';
break;
}
$result = array(
'errors' => $errorMessage,
'recordCount' => 0,
'numFound' => 0,
'start' => 0,
'documents' => array(),
'facets' => array()
);
return $result;
}
/**
* Store the given object into session
*
* @param string $key The key used for reading the value
* @param object $value The object stored in session
*
* @return none
* @access protected
*/
protected function writeSession($key, $value)
{
if(!empty($key) && !empty($value)) {
$_SESSION['EBSCO'][$key] = $value;
}
}
/**
* Read from session the object having the given key
*
* @param string $key The key used for reading the object
*
* @return object
* @access protected
*/
protected function readSession($key)
{
$value = isset($_SESSION['EBSCO'][$key]) ? $_SESSION['EBSCO'][$key] : '';
return $value;
}
/**
* Check if given object is an EBSCOException object
*
* @param object $object
*
* @return boolean
* @access protected
*/
protected function isError($object)
{
return is_a($object, 'EBSCOException');
}
}
?>

432
ebsco/lib/EBSCOConnector.php

@ -0,0 +1,432 @@
<?php
/**
* EBSCOException class
* Used when EBSCO API calls return error messages
*/
class EBSCOException extends Exception
{
const CRITICAL_ERROR = 1;
// Make message argument mandatory
public function __construct($message, $code = self::CRITICAL_ERROR, Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
}
class EBSCOConnector
{
/**
* Error codes defined by EDS API
*/
const EDS_UNKNOWN_PARAMETER = 100;
const EDS_INCORRECT_PARAMETER_FORMAT = 101;
const EDS_INVALID_PARAMETER_INDEX = 102;
const EDS_MISSING_PARAMETER = 103;
const EDS_AUTH_TOKEN_INVALID = 104;
const EDS_INCORRECT_ARGUMENTS_NUMBER = 105;
const EDS_UNKNOWN_ERROR = 106;
const EDS_AUTH_TOKEN_MISSING = 107;
const EDS_SESSION_TOKEN_MISSING = 108;
const EDS_SESSION_TOKEN_INVALID = 109;
const EDS_INVALID_RECORD_FORMAT = 110;
const EDS_UNKNOWN_ACTION = 111;
const EDS_INVALID_ARGUMENT_VALUE = 112;
const EDS_CREATE_SESSION_ERROR = 113;
const EDS_REQUIRED_DATA_MISSING = 114;
const EDS_TRANSACTION_LOGGING_ERROR = 115;
const EDS_DUPLICATE_PARAMETER = 116;
const EDS_UNABLE_TO_AUTHENTICATE = 117;
const EDS_SEARCH_ERROR = 118;
const EDS_INVALID_PAGE_SIZE = 119;
const EDS_SESSION_SAVE_ERROR = 120;
const EDS_SESSION_ENDING_ERROR = 121;
const EDS_CACHING_RESULTSET_ERROR = 122;
const EDS_INVALID_EXPANDER_ERROR = 123;
const EDS_INVALID_SEARCH_MODE_ERROR = 124;
const EDS_INVALID_LIMITER_ERROR = 125;
const EDS_INVALID_LIMITER_VALUE_ERROR = 126;
const EDS_UNSUPPORTED_PROFILE_ERROR = 127;
const EDS_PROFILE_NOT_SUPPORTED_ERROR = 128;
const EDS_INVALID_CONTENT_PROVIDER_ERROR = 129;
const EDS_INVALID_SOURCE_TYPE_ERROR = 130;
const EDS_XSLT_ERROR = 131;
const EDS_RECORD_NOT_FOUND_ERROR = 132;
const EDS_SIMULTANEOUS_USER_LIMIT_ERROR = 133;
const EDS_NO_GUEST_ACCESS_ERROR = 134;
const EDS_DBID_NOT_IN_PROFILE_ERROR = 135;
const EDS_INVALID_SEARCH_VIEW_ERROR = 136;
const EDS_RETRIEVING_FULL_TEXT_ERROR = 137;
/**
* HTTP status codes constants
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*
* @global integer HTTP_OK The request has succeeded
* @global integer HTTP_NOT_FOUND The server has not found anything matching the Request-URI
*/
const HTTP_OK = 200;
const HTTP_BAD_REQUEST = 400;
const HTTP_NOT_FOUND = 404;
const HTTP_INTERNAL_SERVER_ERROR = 500;
/**
* The HTTP_Request object used for API transactions
* @global object HTTP_Request
*/
private $client;
/**
* The URL of the EBSCO API server
* @global string
*/
private static $end_point = 'http://eds-api.ebscohost.com/EDSAPI/rest';
/**
* The URL of the EBSCO API server
* @global string
*/
private static $authentication_end_point = 'https://eds-api.ebscohost.com/AuthService/rest';
/**
* The password used for API transactions
* @global string
*/
private $password;
/**
* The user id used for API transactions
* @global string
*/
private $userId;
/**
* The profile ID used for API transactions
* @global string
*/
private $profileId;
/**
* The interface ID used for API transactions
* @global string
*/
private $interfaceId;
/**
* The customer ID used for API transactions
* @global string
*/
private $orgId;
/**
* The isGuest used for API transactions
* @global string 'y' or 'n'
*/
private $isGuest;
/*
* You can log HTTP_Request requests using this option
* @global bool logAPIRequests
*/
private $logAPIRequests;
/**
* The logger object
* @global object Logger
*/
private $logger;
/**
* Constructor
*
* Sets up the EBSCO API settings
*
* @param none
*
* @access public
*/
public function __construct($config)
{
$this->password = $config['password'];
$this->userId = $config['user'];
$this->interfaceId = $config['interface'];
$this->profileId = $config['profile'];
$this->orgId = $config['organization'];
$this->isGuest = user_is_logged_in() ? 'n' : 'y';
$this->logAPIRequests = ($config['log'] == 1);
if ($this->logAPIRequests) {
$writer = new Zend_Log_Writer_Stream('php://output');
$this->logger = new Zend_Log($writer);
}
}
/**
* Public getter for private isGuest
*
* @param none
*
* @return string isGuest
* @access public
*/
public function isGuest()
{
return $this->isGuest;
}
/**
* Request the authentication token
*
* @param none
*
* @return object SimpleXml or PEAR_Error
* @access public
*/
public function requestAuthenticationToken()
{
$url = self::$authentication_end_point . '/UIDAuth';
// Add the body of the request
$params =<<<BODY
<UIDAuthRequestMessage xmlns="http://www.ebscohost.com/services/public/AuthService/Response/2012/06/01">
<UserId>{$this->userId}</UserId>
<Password>{$this->password}</Password>
<InterfaceId>{$this->interfaceId}</InterfaceId>
</UIDAuthRequestMessage>
BODY;
$response = $this->request($url, $params, array(), 'POST');
return $response;
}
/**
* Request the session token
*
* @param array $headers Authentication token
*
* @return object SimpleXml or PEAR_Error
* @access public
*/
public function requestSessionToken($headers)
{
$url = self::$end_point . '/CreateSession';
// Add the HTTP query params
$params = array(
'profile' => $this->profileId,
'org' => $this->orgId,
'guest' => $this->isGuest
);
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Request the search records
*
* @param array $params Search specific parameters
* @param array $headers Authentication and session tokens
*
* @return object SimpleXml or PEAR_Error
* @access public
*/
public function requestSearch($params, $headers)
{
$url = self::$end_point . '/Search';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Request a specific record
*
* @param array $params Retrieve specific parameters
* @param array $headers Authentication and session tokens
*
* @return object SimpleXml or PEAR_Error
* @access public
*/
public function requestRetrieve($params, $headers)
{
$url = self::$end_point . '/Retrieve';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Request the info data
*
* @param null $params Not used
* @param array $headers Authentication and session tokens
*
* @return object SimpleXml or PEAR_Error
* @access public
*/
public function requestInfo($params, $headers)
{
$url = self::$end_point . '/Info';
$response = $this->request($url, $params, $headers);
return $response;
}
/**
* Send an HTTP request and inspect the response
*
* @param string $url The url of the HTTP request
* @param array $params The parameters of the HTTP request
* @param array $headers The headers of the HTTP request
* @param array $body The body of the HTTP request
* @param string $method The HTTP method, default is 'GET'
*
* @return object SimpleXml or PEAR_Error
* @access protected
*/
protected function request($url, $params, $headers = array(), $method = 'GET')
{
$xml = false;
$return = false;
$data = null;
if (!empty($params)) {
// Arrays of parameters are used only for GET requests
if (is_array($params)) {
$query = http_build_query($params, '', '&');
$query = preg_replace('/\%5B\d+\%5D/', '', $query);
$url = $url . '?' . $query;
// String parameters are used only for POST requests
} else {
$data = $params;
$headers = array_merge(
array('content-type' => 'text/xml'),
$headers
);
}
}
$options = array(
'headers' => $headers,
'method' => $method,
'data' => $data
);
// Send the request
try {
$response = drupal_http_request($url, $options);
//print_r($response);
$code = $response->code;
switch ($code) {
case self::HTTP_OK:
$xml_str = $response->data;
try {
$xml = simplexml_load_string($xml_str);
$return = $xml;
} catch(Exception $e) {
$return = new EBSCOException($xml);
}
break;
case self::HTTP_BAD_REQUEST:
$xml_str = $response->data;
try {
$xml = simplexml_load_string($xml_str);
// If the response is an API error
$isError = isset($xml->ErrorNumber) || isset($xml->ErrorCode);
if ($isError) {
$error = ''; $code = 0;
if (isset($xml->DetailedErrorDescription) && !empty($xml->DetailedErrorDescription)) {
$error = (string) $xml->DetailedErrorDescription;
} else if (isset($xml->ErrorDescription)) {
$error = (string) $xml->ErrorDescription;
} else if (isset($xml->Reason)) {
$error = (string) $xml->Reason;
}
if (isset($xml->ErrorNumber)) {
$code = (integer) $xml->ErrorNumber;
} else if (isset($xml->ErrorCode)) {
$code = (integer) $xml->ErrorCode;
}
$return = new EBSCOException($error, $code);
} else {
$return = new EBSCOException("HTTP {$code} : The request could not be understood
by the server due to malformed syntax. Modify your search before retrying.");
}
} catch (Exception $e) {
$return = new EBSCOException($xml);
}
break;
case self::HTTP_NOT_FOUND:
$return = new EBSCOException("HTTP {$code} : The resource you are looking for might
have been removed, had its name changed, or is temporarily unavailable.");
break;
case self::HTTP_INTERNAL_SERVER_ERROR:
$return = new EBSCOException("HTTP {$code} : The server encountered an unexpected condition
which prevented it from fulfilling the request.");
break;
default:
$return = new EBSCOException("HTTP {$code} : Unexpected HTTP error.");
break;
}
} catch (Exception $e) {
$return = new EBSCOException($response);
}
// Log any error
/*if ($this->logAPIRequests) {
// $client = both the HTTP request and response
// $response = only the HTTP response
$message = $this->toString($client); // or $this->toString($response)
$this->logger->log($message, Zend_Log::ERR);
}*/
return $return;
}
/*
* Capture the output of print_r into a string
*
* @param object Any object
* @access private
*/
private function toString($object)
{
ob_start();
print_r($object);
return ob_get_clean();
}
}
?>

788
ebsco/lib/EBSCODocument.php

@ -0,0 +1,788 @@
<?php
/**
* The EBSCO Document model class
*
* It provides all the methods and properties needed for :
* - setting up and performing API calls
* - displaying results in UI
* - displaying statistics about the search, etc
*
* PHP version 5
*
*/
require_once 'EBSCOAPI.php';
require_once 'EBSCORecord.php';
class EBSCODocument
{
/**
* The EBSCOAPI object that performs the API calls
* @global object EBSCOAPI
*/
private $eds = null;
/**
* The associative array of current request parameters
* @global array
*/
private $params = array();
/**
* The associative array of EBSCO results returned by a Search API call
* #global array
*/
private $results = array();
/**
* The associative array of data returned by a Retrieve API call
* @global array
*/
private $result = array();
/**
* The array of data returned by an Info API call
* @global array
*/
private $info = array();
/**
* The EBSCORecord model returned by a Retrieve API call
* #global object EBSCORecord
*/
private $record = null;
/**
* The array of EBSCORecord models returned by a Search API call
* #global array of EBSCORecord objects
*/
private $records = array();
/**
* The array of filters currently applied
* @global array
*/
private $filters = array();
/**
* Maximum number of results returned by Search API call
* @global integer
*/
private $limit = 10;
/**
* Maximum number of links displayed by the pagination
* @global integer
*/
private static $page_links = 10;
/**
* Limit options
* global array
*/
private static $limit_options = array(
10 => 10,
20 => 20,
30 => 30,
40 => 40,
50 => 50
);
/**
* Sort options
* global array
*/
private static $sort_options = array(
'relevance' => 'Relevance',
'date_desc' => 'Date Descending',
'date_asc' => 'Date Ascending'
);
/**
* Amount options
* global array
*/
private static $amount_options = array(
'detailed' => 'Detailed',
'brief' => 'Brief',
'title' => 'Title Only'
);
/**
* Bool options
* global array
*/
private static $bool_options = array(
'AND' => 'All terms',
'OR' => 'Any terms',
'NOT' => 'No terms'
);
/**
* Search mode options
* global array
*/
private static $mode_options = array(
'all' => 'All search terms',
'bool' => 'Boolean / Phrase',
'any' => 'Any search terms',
'smart' => 'SmartText Searching'
);
/**
* Basic search type options
* global array
*/
private static $basic_search_type_options = array(
'AllFields' => 'All Text',
'Title' => 'Title',
'Author' => 'Author',
'Subject' => 'Subject terms',
'Source' => 'Source',
'Abstract' => 'Abstract'
);
/**
* Advanced search type options
* global array
*/
private static $advanced_search_type_options = array(
'AllFields' => 'All Text',
'Title' => 'Title',
'Author' => 'Author',
'Subject' => 'Subject terms'
);
/**
* Constructor.
*
* @param array $data Raw data from the EBSCO search representing the record.
*/
public function __construct($params = null)
{
$this->eds = new EBSCOAPI(array(
'password' => variable_get('ebsco_password'),
'user' => variable_get('ebsco_user'),
'profile' => variable_get('ebsco_profile'),
'interface' => variable_get('ebsco_interface'),
'organization' => variable_get('ebsco_organization'),
'guest' => variable_get('ebsco_guest'),
'log' => variable_get('ebsco_log')
));
$this->params = $params ? $params : $_REQUEST;
$this->limit = variable_get('ebsco_default_limit') ? variable_get('ebsco_default_limit') : $this->limit;
}
/**
* Perform the API Info call
*
* @return array
*/
public function info()
{
$this->info = $this->eds->apiInfo();
return $this->info;
}
/**
* Perform the API Retrieve call
*
* @return array
*/
public function retrieve()
{
list($an, $db) = isset($this->params['id']) ? explode('|', $this->params['id'], 2) : array(null, null);
$this->result = $this->eds->apiRetrieve($an, $db);
return $this->result;
}
/**
* Perform the API Search call
*
* @return array
*/
public function search()
{
$search = array();
if (isset($this->params['lookfor']) && isset($this->params['type'])) {
$search = array(
'lookfor' => $this->params['lookfor'],
'index' => $this->params['type']
);
} else if (isset($this->params['group'])) {
$search = $this->params;
} else {
return array();
}
$filter = isset($this->params['filter']) ? $this->params['filter'] : array();
$page = isset($this->params['page']) ? $this->params['page'] + 1 : 1;
$limit = $this->limit;
$sort = isset($this->params['sort']) ? $this->params['sort'] : 'relevance';
$amount = isset($this->params['amount']) ? $this->params['amount'] : 'detailed';
$mode = isset($this->params['mode']) ? $this->params['mode'] : 'all';
$this->results = $this->eds->apiSearch($search, $filter, $page, $limit, $sort, $amount, $mode);
if (isset($this->results['start'])) {
$this->results['start'] = $limit * ($page - 1);
}
return $this->results;
}
/**
* Get the EBSCORecord model for the result
*
** @return array
*/
public function record()
{
if (empty($this->record) && !(empty($this->result))) {
$this->record = new EBSCORecord($this->result);
}
return $this->record;
}
/**
* Get the EBSCORecord models array from results array
*
** @return array
*/
public function records()
{
if (empty($this->records) && !(empty($this->results))) {
foreach($this->results['documents'] as $result) {
$this->records[] = new EBSCORecord($result);
}
}
return $this->records;
}
/**
* Get the pagination HTML string
*
** @return HTML string
*/
public function pager()
{
$pager = null;
if ($this->has_records()) {
pager_default_initialize($this->record_count() / $this->limit, 1);
$pager = theme('pager', array('tags' => null, 'quantity' => self::$page_links));
$pager = preg_replace('/<li class="pager-last last">(.*)<\/li>/', '', $pager);
}
return $pager;
}
/********************************************************
*
* Getters (class methods)
*
********************************************************/
/**
* Getter for sort options
* @return array
*/
public static function limit_options()
{
return self::$limit_options;
}
/**
* Getter for sort options
* @return array
*/
public static function sort_options()
{
return self::$sort_options;
}
/**
* Getter for amount options
* @return array
*/
public static function amount_options()
{
return self::$amount_options;
}
/**
* Getter for boolean options
* @return array
*/
public static function bool_options()
{
return self::$bool_options;
}
/**
* Getter for search mode options
* @return array
*/
public static function mode_options()
{
return self::$mode_options;
}
/**
* Getter for Basic search type options
* @return array
*/
public static function basic_search_type_options()
{
return self::$basic_search_type_options;
}
/**
* Getter for Advanced search type options
* @return array
*/
public static function advanced_search_type_options()
{
return self::$advanced_search_type_options;
}
/********************************************************
*
* Helper methods
*
********************************************************/
/**
* Get the expanders.
*
* @return array
*/
public function expanders()
{
$actions = array();
$filters = $this->filters();
foreach($filters as $filter) {
$actions[] = $filter['action'];
}
$expanders = isset($this->info['expanders']) ? $this->info['expanders'] : array();
foreach($expanders as $key => $expander) {
if (in_array($expander['Action'], $actions)) {
$expanders[$key]['selected'] = true;
}
}
return $expanders;
}
/**
* Get the facets.
*
* @return array
*/
public function facets()
{
$actions = array();
foreach($this->filters as $filter) {
$actions[] = $filter['action'];
}
$facets = isset($this->results['facets']) ? $this->results['facets'] : array();
foreach($facets as $key => $cluster) {
foreach($cluster['Values'] as $k => $facet) {
$is_applied = false;
if (in_array($facet['Action'], $actions)) {
$is_applied = true;
}
$facets[$key]['Values'][$k]['applied'] = $is_applied;
}
}
return $facets;
}
/**
* Get the filters.
*
* @return array
*/
public function filters()
{
if (!empty($_REQUEST['filter'])) {
$labels = array();
foreach($this->info['limiters'] as $limiter) {
$labels[$limiter['Id']] = $limiter['Label'];
}
$this->filters = array();
foreach($_REQUEST['filter'] as $filter) {
if (!empty($filter)) {
$temp = str_replace(array('addfacetfilter(', 'addlimiter(', 'addexpander('), array('', '', ''), $filter);
if (substr($temp, -1, 1) == ')') {
$temp = substr($temp, 0, -1);
}
// Do not display addfacetfilter, addlimiter or addexpander strings
if (preg_match('/\:/', $filter)) {
list($field, $value) = explode(':', $temp, 2);
$displayField = isset($labels[$field]) ? $labels[$field] : $field;
$displayValue = $value == 'y' ? 'yes' : $value;
} else if (preg_match('/addexpander/', $filter)) {
$field = $temp;
$value = 'y';
$displayField = isset($labels[$field]) ? $labels[$field] : $field;
$displayValue = 'yes';
} else {
$field = $value = $displayField = $displayValue = $filter;
}
$this->filters[] = array(
'field' => $field,
'value' => $value,
'action' => $filter,
'displayField' => $displayField,
'displayValue' => $displayValue,
);
}
}
}
return $this->filters;
}
/**
* Get the limiters.
*
* @return array
*/
public function limiters()
{
$actions = array(); $ids = array();
$filters = $this->filters();
foreach($filters as $filter) {
$actions[] = $filter['action'];
$ids[] = $filter['field'];
}
$limiters = isset($this->info['limiters']) ? $this->info['limiters'] : array();
foreach($limiters as $key => $cluster) {
// multi select limiter
if (!empty($cluster['Values'])) {
foreach($cluster['Values'] as $limiter) {
$action = $limiter['Action'];
if (in_array($action, $actions)) {
$limiters[$key]['selected'][] = $limiter['Action'];
}
}
// date limiter
} else if ($cluster['Type'] == 'ymrange') {
$id = $cluster['Id'];
if (($k = array_search($id, $ids)) !== false) {
$limiters[$key]['selected'] = $filters[$k]['action'];
}
// other limiters
} else {
$action = str_replace('value', 'y', $cluster['Action']);
if (in_array($action, $actions)) {
$limiters[$key]['selected'] = true;
}
}
}
return $limiters;
}
/**
* Get the total number of records.
*
* @return integer
*/
public function record_count()
{
return !empty($this->results) ? $this->results['recordCount'] : 0;
}
/**
* Get the number of end record.
*
* @return integer
*/
public function record_end()
{
$count = !empty($this->results) ? count($this->results['documents']) : 0;
$start = !empty($this->results) ? $this->results['start'] : 0;
return $start + $count;
}
/**
* Get the number of start record.
*
* @return integer
*/
public function record_start()
{
return !empty($this->results) ? $this->results['start'] + 1 : 0;
}
/**
* Get the search time
*
* @return decimal number
*/
public function search_time()
{
return !empty($this->results) &&
isset($this->results['searchTime']) ? $this->results['searchTime'] : 0;
}
/**
* Get the search view : basic or advanced
*
* @return string
*/
public function search_view()
{
if (isset($_REQUEST['group'])) {
return 'advanced';
} else {
return 'basic';
}
}
/**
* Hidden params used by UpdateForm
*
* @return array
*/
public function search_params()
{
$params = $this->link_search_params();
// filter the params that have same values as sidebar checkboxes, otherwise they will produce duplicates
$not_allowed_values = array(
'addexpander(thesaurus)',
'addexpander(fulltext)',
'addlimiter(FT:y)',
'addlimiter(RV:y)',
'addlimiter(SO:y)'
);
$params = $this->array_filter_recursive($params, function($item) use($not_allowed_values) {
return !($item && in_array($item, $not_allowed_values));
});
return array_filter($params);
}
/**
* Hidden params used by UpdateForm
*
* @return array
*/
public function link_search_params()
{
// filter the page parameter
$not_allowed_keys = array('page', 'ui', 'has_js', 'op', 'submit', 'form_id', 'form_build_id');
$query="";
if(isset($_SERVER['QUERY_STRING']))
{$query = urldecode($_SERVER['QUERY_STRING']);}
parse_str($query, $params);
$params = $this->array_unset_recursive($params, $not_allowed_keys);
return $params;
}
/**
* Check if there are records in results array
*
** @return boolean
*/
public function has_records()
{
return !empty($this->results) && !empty($this->results['documents']);
}
/**
* Create the last search data
*
* @return void
*/
public function search_create($query = null)
{
$last_search = array();
if (!empty($this->results)) {
$results_identifiers = array();
foreach($this->results['documents'] as $result) {
$results_identifiers[] = $result['id'];
}
$last_search['query'] = $query ? $query : $_SERVER['QUERY_STRING'];
$last_search['records'] = serialize($results_identifiers);
$last_search['count'] = $this->record_count();
}
return $last_search;
}
/**
* Save last search data in session
*
* @return void
*/
public function search_write($query = null)
{
$_SESSION['EBSCO']['last-search'] = $this->search_create($query);
}
/**
* Load last search data from session
*
* @return array
*/
public function search_read($id = null, $op = null)
{
$params = array();
$lastSearch = $_SESSION['EBSCO']['last-search'];
if ($lastSearch) {
$lastSearch['records'] = unserialize($lastSearch['records']);
if ($id) {
parse_str($lastSearch['query'], $params);
$params['page'] = (int) (isset($params['page']) ? $params['page'] : 0);
$index = array_search($id, $lastSearch['records']);
// if this is not the first scroll and if this is not a page refresh
if (isset($lastSearch['current']) && $lastSearch['current'] != $id) {
// if we change page
if (($op == 'Next' && $index % $this->limit === 0) ||
($op == 'Previous' && $index % $this->limit === 9)) {
$params['page'] = ($op == 'Next') ? $params['page'] + 1 : $params['page'] - 1;
$query = drupal_http_build_query($params);
$lastSearch['query'] = $_SESSION['EBSCO']['last-search']['query'] = $query;
}
}
$start = $params['page'];
if (count($lastSearch['records']) > 10) {
$records = array_slice($lastSearch['records'], $index - $index % $this->limit, $this->limit);
} else {
$records = $lastSearch['records'];
}
if (!isset($lastSearch['records'][$index + 1])) {
$params['page'] += 1;
$driver = new EBSCODocument($params);
$driver->search();
$query = drupal_http_build_query($params);
$newSearch = $driver->search_create($query);
$newSearch['records'] = unserialize($newSearch['records']);
$lastSearch['records'] = array_merge($lastSearch['records'], $newSearch['records']);
$_SESSION['EBSCO']['last-search']['records'] = serialize($lastSearch['records']);
if ($op == 'Next') {
$lastSearch['previous'] = isset($records[8]) ? $records[8] : '';
}
$lastSearch['next'] = isset($newSearch['records'][0]) ? $newSearch['records'][0] : '';
} else {
$lastSearch['next'] = $lastSearch['records'][$index + 1];
}
if (!isset($lastSearch['records'][$index - 1])) {
if ($params['page'] > 0) {
$params['page'] -= 1;
$driver = new EBSCODocument($params);
$driver->search();
$query = drupal_http_build_query($params);
$newSearch = $driver->search_create($query);
$newSearch['records'] = unserialize($newSearch['records']);
$lastSearch['records'] = array_merge($lastSearch['records'], $newSearch['records']);
$_SESSION['EBSCO']['last-search']['records'] = serialize($lastSearch['records']);
$lastSearch['previous'] = isset($newSearch['records'][9]) ? $newSearch['records'][9] : '';
if ($op == 'Previous') {
$lastSearch['next'] = isset($records[1]) ? $records[1] : '';
}
} else {
$lastSearch['previous'] = '';
}
} else {
$lastSearch['previous'] = $lastSearch['records'][$index - 1];
}
$lastSearch['current_index'] = $start * $this->limit + $index % $this->limit + 1;
$lastSearch['current'] = $id;
}
}
$_SESSION['EBSCO']['last-search']['current'] = $id;
return $lastSearch;
}
/**
* A recursive array_filter
*
* @return array
*/
private function array_filter_recursive($input, $callback = null)
{
foreach ($input as &$value) {
if (is_array($value)) {
$value = $this->array_filter_recursive($value, $callback);
}
}
return array_filter($input, $callback);
}
/**
* Recursive filter an array using the given $keys
*
* @return array
*/
private function array_unset_recursive($input, $keys) {
foreach($keys as $key) {
if (isset($input[$key])) {
unset($input[$key]);
}
}
if (is_array($input)) {
foreach ($input as $key => $value) {
$input[$key] = is_array($value) ? $this->array_unset_recursive($value, $keys) : $value;
}
}
return array_filter($input);
}
}

398
ebsco/lib/EBSCORecord.php

@ -0,0 +1,398 @@
<?php
/**
* The EBSCO record object
*
* PHP version 5
*
*/
class EBSCORecord
{
/**
* The array of data
* @global array
*/
private $data = array();
/**
* The result id (the EBSCO counter) of the record
* @global integer
*/
public $result_id = null;
/**
* The id of the record
* @global integer
*/
public $record_id = null;
/**
* The summary of the record.
* @global string
*/
public $summary = null;
/**
* The authors of the record.
* @global string
*/
public $authors = null;
/**
* The subjects of the record.
* @global string
*/
public $subjects = null;
/**
* The custom links provided for the record.
* @global array
*/
public $custom_links = array();
/**
* The database label of the record.
* @global string
*/
public $db_label = null;
/**
* The full-text availability of the record.
* @global boolean
*/
public $full_text_availability = null;
/**
* The full text of the record.
* @global string
*/
public $full_text = null;
/**
* The PDF availability of the record.
* @global boolean
*/
public $pdf_availability = null;
/**
* The items of the record.
* @global array
*/
public $items = array();
/**
* The external link of the record.
* @global string
*/
public $p_link = null;
/**
* The external link to the PDF version of the record.
* @global string
*/
public $pdf_link = null;
/**
* The publication type link of the record.
* @global string
*/
public $publication_type = null;
/**
* The external thumbnails links of the record.
* @global string
*/
public $small_thumb_link = null;
public $medium_thumb_link = null;
/**
* The title of the record.
* @global string
*/
public $title = null;
/**
* The source of the record.
* @global string
*/
public $source = null;
/**
* The access level of the record.
* @global string
*/
public $access_level = null;
/**
* Constructor.
*
* @param array $data Raw data from the EBSCO search representing the record.
*/
public function __construct($data = array())
{
$this->data = $data;
$this->record_id = $this->record_id();
$this->result_id = $this->result_id();
$this->title = $this->title();
$this->summary = $this->summary();
$this->authors = $this->authors();
$this->subjects = $this->subjects();
$this->custom_links = $this->custom_links();
$this->db_label = $this->db_label();
$this->full_text_availability = $this->full_text_availability();
$this->full_text = $this->full_text();
$this->items = $this->items();
$this->p_link = $this->p_link();
$this->publication_type = $this->publication_type();
$this->pdf_availability = $this->pdf_availability();
$this->pdf_link = $this->pdf_link();
$this->small_thumb_link = $this->thumb_link();
$this->medium_thumb_link = $this->thumb_link('medium');
$this->source = $this->source();
$this->access_level = $this->access_level();
}
/********************************************************
*
* Getters
*
********************************************************/
/**
* Get the summary of the record.
*
* @return string
*/
public function access_level()
{
return isset($this->data['AccessLevel']) ?
$this->data['AccessLevel'] : '';
}
/**
* Get the summary of the record.
*
* @return string
*/
public function summary()
{
return isset($this->data['Items']['Abstract']) ?
$this->data['Items']['Abstract']['Data'] : '';
}
/**
* Get the authors of the record.
*
* @return string
*/
public function authors()
{
return isset($this->data['Items']['Author']) ?
$this->data['Items']['Author']['Data'] : '';
}
/**
* Get the custom links of the record.
*
* @return array
*/
public function custom_links()
{
return isset($this->data['CustomLinks']) ?
$this->data['CustomLinks'] : array();
}
/**
* Get the database label of the record.
*
* @return string
*/
public function db_label()
{
return isset($this->data['DbLabel']) ?
$this->data['DbLabel'] : '';
}
/**
* Get the full text availability of the record.
*
* @return boolean
*/
public function full_text()
{
return isset($this->data['FullText']) &&
isset($this->data['FullText']['Value']) ? $this->data['FullText']['Value'] : '';
}
/**
* Get the full text availability of the record.
*
* @return boolean
*/
public function full_text_availability()
{
return isset($this->data['FullText']) &&
$this->data['FullText']['Availability'];
}
/**
* Get the items of the record.
*
* @return array
*/
public function items()
{
return isset($this->data['Items']) ? $this->data['Items'] : array();
}
/**
* Get the external url of the record.
*
* @return string
*/
public function p_link()
{
return isset($this->data['PLink']) ? $this->data['PLink'] : '';
}
/**
* Get the publication type of the record.
*
* @return string
*/
public function publication_type()
{
return isset($this->data['PubType']) ? $this->data['PubType'] : '';
}
/**
* Get the PDF availability of the record.
*
* @return boolean
*/
public function pdf_availability()
{
return isset($this->data['FullText']) &&
isset($this->data['FullText']['Links']) &&
isset($this->data['FullText']['Links']['pdflink']) &&
$this->data['FullText']['Links']['pdflink'];
}
/**
* Get the PDF url of the record.
*
* @return string
*/
public function pdf_link()
{
return isset($this->data['FullText']) &&
isset($this->data['FullText']['Links']) &&
isset($this->data['FullText']['Links']['pdflink']) ?
$this->data['FullText']['Links']['pdflink'] :
'';
}
/**
* Get the result id of the record.
*
* @return integer
*/
public function result_id()
{
return isset($this->data['ResultId']) ?
$this->data['ResultId'] : '';
}
/**
* Get the subject data of the record.
*
* @return string
*/
public function subjects()
{
return isset($this->data['Items']['Subject']) ?
$this->data['Items']['Subject']['Data'] : '';
}
/**
* Return a URL to a thumbnail preview of the record, if available; false
* otherwise.
*
* @param string $size Size of thumbnail (small, medium or large -- small is
* default).
*
* @return string
*/
public function thumb_link($size = 'small')
{
$imageInfo = isset($this->data['ImageInfo']) ? $this->data['ImageInfo'] : '';
if ($imageInfo && isset($imageInfo['thumb'])) {
switch ($size) {
case 'large':
case 'medium':
return $imageInfo['medium'];
break;
case 'small':
default:
return $imageInfo['thumb'];
break;
}
}
return false;
}
/**
* Get the title of the record.
*
* @return string
*/
public function title()
{
return isset($this->data['Items']['Title']) ?
$this->data['Items']['Title']['Data'] : '';
}
/**
* Get the source of the record.
*
* @return string
*/
public function source()
{
return isset($this->data['Items']['TitleSource']) ?
$this->data['Items']['TitleSource']['Data'] : '';
}
/**
* Return the identifier of this record within the EBSCO databases
*
* @return string Unique identifier.
*/
public function record_id()
{
return isset($this->data['id']) ?
$this->data['id'] : '';
}
}

547
ebsco/lib/EBSCOResponse.php

@ -0,0 +1,547 @@
<?php
/**
* EBSCO Response class
*
* PHP version 5
*
*/
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. &lt; => <)
$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;
}
}
?>

444
ebsco/lib/sanitizer.class.php

@ -0,0 +1,444 @@
<?php // $Id$
// vim: expandtab sw=4 ts=4 sts=4:
# ***** BEGIN LICENSE BLOCK *****
# This file is part of HTML Sanitizer.
# Copyright (c) 2005-2011 Frederic Minne <zefredz@gmail.com>.
# All rights reserved.
#
# HTML Sanitizer is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# HTML Sanitizer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with HTML Sanitizer; if not, see <http://www.gnu.org/licenses/>.
#
# ***** END LICENSE BLOCK *****
/**
* Sanitize HTML contents :
* Remove dangerous tags and attributes that can lead to security issues like
* XSS or HTTP response splitting
*
* @author Frederic Minne <zefredz@gmail.com>
* @copyright Copyright &copy; 2005-2011, Frederic Minne
* @license http://www.gnu.org/licenses/lgpl.txt GNU Lesser General Public License version 3 or later
* @version 1.1
*/
class HTML_Sanitizer
{
// Private fields
private $_allowedTags;
private $_allowJavascriptEvents;
private $_allowJavascriptInUrls;
private $_allowObjects;
private $_allowScript;
private $_allowStyle;
private $_additionalTags;
/**
* Constructor
*/
public function __construct()
{
$this->resetAll();
}
/**
* (re)set all options to default value
*/
public function resetAll()
{
$this->_allowDOMEvents = false;
$this->_allowJavascriptInUrls = false;
$this->_allowStyle = false;
$this->_allowScript = false;
$this->_allowObjects = false;
$this->_allowStyle = false;
$this->_allowedTags = '<a><br><b><h1><h2><h3><h4><h5><h6>'
. '<img><li><ol><p><strong><table><tr><td><th><u><ul><thead>'
. '<tbody><tfoot><em><dd><dt><dl><span><div><del><add><i><hr>'
. '<pre><br><blockquote><address><code><caption><abbr><acronym>'
. '<cite><dfn><q><ins><sup><sub><kbd><samp><var><tt><small><big>'
;
$this->_additionalTags = '';
}
/**
* Add additional tags to allowed tags
* @param string
* @access public
*/
public function addAdditionalTags( $tags )
{
$this->_additionalTags .= $tags;
}
/**
* Allow iframes
* @access public
*/
public function allowIframes()
{
$this->addAdditionalTags( '<iframe>' );
}
/**
* Allow HTML5 media tags
* @access public
*/
public function allowHtml5Media()
{
$this->addAdditionalTags( '<canvas><video><audio>' );
}
/**
* Allow object, embed, applet and param tags in html
* @access public
*/
public function allowObjects()
{
$this->_allowObjects = true;
}
/**
* Allow DOM event on DOM elements
* @access public
*/
public function allowDOMEvents()
{
$this->_allowDOMEvents = true;
}
/**
* Allow script tags
* @access public
*/
public function allowScript()
{
$this->_allowScript = true;
}
/**
* Allow the use of javascript: in urls
* @access public
*/
public function allowJavascriptInUrls()
{
$this->_allowJavascriptInUrls = true;
}
/**
* Allow style tags and attributes
* @access public
*/
public function allowStyle()
{
$this->_allowStyle = true;
}
/**
* Helper to allow all javascript related tags and attributes
* @access public
*/
public function allowAllJavascript()
{
$this->allowDOMEvents();
$this->allowScript();
$this->allowJavascriptInUrls();
}
/**
* Allow all tags and attributes
* @access public
*/
public function allowAll()
{
$this->allowAllJavascript();
$this->allowObjects();
$this->allowStyle();
$this->allowIframes();
$this->allowHtml5Media();
}
/**
* Filter URLs to avoid HTTP response splitting attacks
* @access public
* @param string url
* @return string filtered url
*/
public function filterHTTPResponseSplitting( $url )
{
$dangerousCharactersPattern = '~(\r\n|\r|\n|%0a|%0d|%0D|%0A)~';
return preg_replace( $dangerousCharactersPattern, '', $url );
}
/**
* Remove potential javascript in urls
* @access public
* @param string url
* @return string filtered url
*/
public function removeJavascriptURL( $str )
{
$HTML_Sanitizer_stripJavascriptURL = 'javascript:[^"]+';
$str = preg_replace("/$HTML_Sanitizer_stripJavascriptURL/i"
, '__forbidden__'
, $str );
return $str;
}
/**
* Remove potential flaws in urls
* @access private
* @param string url
* @return string filtered url
*/
private function sanitizeURL( $url )
{
if ( ! $this->_allowJavascriptInUrls )
{
$url = $this->removeJavascriptURL( $url );
}
$url = $this->filterHTTPResponseSplitting( $url );
return $url;
}
/**
* Callback for PCRE
* @access private
* @param matches array
* @return string
* @see sanitizeURL
*/
private function _sanitizeURLCallback( $matches )
{
return 'href="'.$this->sanitizeURL( $matches[1] ).'"';
}
/**
* Remove potential flaws in href attributes
* @access private
* @param string html tag
* @return string filtered html tag
*/
private function sanitizeHref( $str )
{
$HTML_Sanitizer_URL = 'href="([^"]+)"';
return preg_replace_callback("/$HTML_Sanitizer_URL/i"
, array( &$this, '_sanitizeURLCallback' )
, $str );
}
/**
* Callback for PCRE
* @access private
* @param matches array
* @return string
* @see sanitizeURL
*/
private function _sanitizeSrcCallback( $matches )
{
return 'src="'.$this->sanitizeURL( $matches[1] ).'"';
}
/**
* Remove potential flaws in href attributes
* @access private
* @param string html tag
* @return string filtered html tag
*/
private function sanitizeSrc( $str )
{
$HTML_Sanitizer_URL = 'src="([^"]+)"';
return preg_replace_callback("/$HTML_Sanitizer_URL/i"
, array( &$this, '_sanitizeSrcCallback' )
, $str );
}
/**
* Remove dangerous attributes from html tags
* @access private
* @param string html tag
* @return string filtered html tag
*/
private function removeEvilAttributes( $str )
{
if ( ! $this->_allowDOMEvents )
{
$str = preg_replace_callback('/<(.*?)>/i'
, array( &$this, '_removeDOMEventsCallback' )
, $str );
}
if ( ! $this->_allowStyle )
{
$str = preg_replace_callback('/<(.*?)>/i'
, array( &$this, '_removeStyleCallback' )
, $str );
}
return $str;
}
/**
* Remove DOM events attributes from html tags
* @access private
* @param string html tag
* @return string filtered html tag
*/
private function removeDOMEvents( $str )
{
$str = preg_replace ( '/\s*=\s*/', '=', $str );
$HTML_Sanitizer_stripAttrib = '(onclick|ondblclick|onmousedown|'
. 'onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|'
. 'onkeyup|onfocus|onblur|onabort|onerror|onload)'
;
$str = stripslashes( preg_replace("/$HTML_Sanitizer_stripAttrib/i"
, 'forbidden'
, $str ) );
return $str;
}
/**
* Callback for PCRE
* @access private
* @param matches array
* @return string
* @see removeDOMEvents
*/
private function _removeDOMEventsCallback( $matches )
{
return '<' . $this->removeDOMEvents( $matches[1] ) . '>';
}
/**
* Remove style attributes from html tags
* @access private
* @param string html tag
* @return string filtered html tag
*/
private function removeStyle( $str )
{
$str = preg_replace ( '/\s*=\s*/', '=', $str );
$HTML_Sanitizer_stripAttrib = '(style)'
;
$str = stripslashes( preg_replace("/$HTML_Sanitizer_stripAttrib/i"
, 'forbidden'
, $str ) );
return $str;
}
/**
* Callback for PCRE
* @access private
* @param matches array
* @return string
* @see removeStyle
*/
private function _removeStyleCallback( $matches )
{
return '<' . $this->removeStyle( $matches[1] ) . '>';
}
/**
* Remove dangerous HTML tags
* @access private
* @param string html code
* @return string filtered url
*/
private function removeEvilTags( $str )
{
$allowedTags = $this->_allowedTags;
if ( $this->_allowScript )
{
$allowedTags .= '<script>';
}
if ( $this->_allowStyle )
{
$allowedTags .= '<style>';
}
if ( $this->_allowObjects )
{
$allowedTags .= '<object><embed><applet><param>';
}
$allowedTags .= $this->_additionalTags;
$str = strip_tags($str, $allowedTags );
return $str;
}
/**
* Sanitize HTML
* remove dangerous tags and attributes
* clean urls
* @access public
* @param string html code
* @return string sanitized html code
*/
public function sanitize( $html )
{
$html = $this->removeEvilTags( $html );
$html = $this->removeEvilAttributes( $html );
$html = $this->sanitizeHref( $html );
$html = $this->sanitizeSrc( $html );
return $html;
}
}
function html_sanitize( $str )
{
static $san = null;
if ( empty( $san ) )
{
$san = new HTML_Sanitizer;
}
return $san->sanitize( $str );
}
function html_loose_sanitize( $str )
{
static $san = null;
if ( empty( $san ) )
{
$san = new HTML_Sanitizer;
$san->allowAll();
}
return $san->sanitize( $str );
}

44
ebsco/templates/ebsco-advanced-search.tpl.php

@ -0,0 +1,44 @@
<?php
/**
* @file
* Displays the advanced search form.
*
* @see template_preprocess_ebsco_advanced_search()
*/
?>
<div class="container-inline ebsco-advanced">
<?php print $search_form; ?>
</div>
<div class="offscreen" id="advanced-row-template">
<fieldset id="edit-groupNN" class="form-wrapper _advanced-row">
<div class="fieldset-wrapper">
<div class="form-item form-type-select form-item-groupNN-bool">
<select id="ebsco-advanced-search-boolNN" name="groupNN[bool]" class="form-select">
<option value="AND" selected="selected">All terms</option>
<option value="OR">Any terms</option>
<option value="NOT">No terms</option>
</select>
</div>
<div class="form-item form-type-textfield form-item-groupNN-lookfor">
<input title="Enter the terms you wish to search for." type="text" id="ebsco-advanced-search-lookforNN" name="groupNN[lookfor]" value="" size="30" maxlength="128" class="form-text" />
</div>
<div class="form-item form-type-select form-item-groupNN-type">
<label for="ebsco-advanced-search-type1">in</label>
<select id="ebsco-advanced-search-typeNN" name="groupNN[type]" class="form-select">
<option value="AllFields" selected="selected">All Text</option>
<option value="Title">Title</option>
<option value="Author">Author</option>
<option value="Subject">Subject terms</option>
</select>
</div>
<div class="delete-search">
<a href="#" class="delete _delete_row" id="delete_search_link_NN">
<?php print t('Remove Search Field'); ?>
</a>
</div>
</div>
</fieldset>
</div>

27
ebsco/templates/ebsco-basic-search.tpl.php

@ -0,0 +1,27 @@
<?php
/**
* @file
* Displays the basic search form block.
*
* @see template_preprocess_ebsco_basic_search()
*/
?>
<div class="container-inline">
<?php if ($search_view == 'basic'): ?>
<?php print $search_form; ?>
<?php elseif ($search_view == 'advanced'): ?>
<a href="<?php print url('ebsco/advanced', array('query' => array('edit' => 1))); ?>" class="small">
<?php print t('Edit this Advanced Search'); ?>
</a> |
<a href="<?php print url('ebsco/advanced'); ?>" class="small">
<?php print t('Start a new Advanced Search'); ?>
</a> |
<a href="<?php print url('ebsco/results'); ?>" class="small">
<?php print t('Start a new Basic Search'); ?>
</a>
<br/>
<?php print t('Your search terms'); ?> : <strong><?php print check_plain($lookfor); ?></strong>
<?php endif; ?>
</div>

134
ebsco/templates/ebsco-result.tpl.php

@ -0,0 +1,134 @@
<?php
/**
* @file
* Default theme implementation for displaying an EBSCO result.
*
* @see template_preprocess_ebsco_result()
*/
?>
<?php if ($record): ?>
<?php
$id = check_plain($record->record_id());
$fulltextUrl = url('ebsco/fulltext', array('query' => array('id' => $id)));
$pdfUrl = url('ebsco/pdf', array('query' => array('id' => $id)));
?>
<div class="ebsco-record">
<h1><?php print $record->title; ?></h1>
<div class="record-toolbar">
<?php if ($last_search): ?>
<div class="floatright">
<?php if ($last_search['previous']): ?>
<a href="<?php print url('ebsco/result', array('query' => array('id' => $last_search['previous'], 'op' => 'Previous'))); ?>" class="_record_link">
&laquo; <?php print t('Previous'); ?>
</a>
<?php endif; ?>
#<?php print $last_search['current_index']; ?> of <?php print $last_search['count']; ?>
<?php if ($last_search['next']): ?>
<a href="<?php print url('ebsco/result', array('query' => array('id' => $last_search['next'], 'op' => 'Next'))); ?>" class="_record_link">
<?php print t('Next'); ?> &raquo;
</a>
<?php endif; ?>
</div>
<div class="floatleft">
<a href="<?php print "?{$last_search['query']}"; ?>">
&laquo; <?php print t('Back to Results list'); ?>
</a>
</div>
<div class="clear"></div>
<?php endif; ?>
</div>
<div class="span-5">
<ul class="external-links">
<?php if($record->p_link): ?>
<li>
<a href="<?php print $record->p_link; ?>">
<?php print t('View in EDS'); ?>
</a>
</li>
<?php endif; ?>
<?php if ($record->pdf_link): ?>
<li>
<a href="<?php print $pdfUrl; ?>" class="icon pdf fulltext">
<?php print t('PDF full text'); ?>
</a>
</li>
<?php endif; ?>
<?php if ($record->full_text_availability): ?>
<li>
<a href="<?php if (!user_is_logged_in()) { print $fulltextUrl; } ?>#html" class="icon html fulltext">
<?php print t('HTML full text'); ?>
</a>
</li>
<?php endif; ?>
<?php if (!empty($record->custom_links)): ?>
<?php foreach ($record->custom_links as $link): ?>
<li>
<a href="<?php print $link['Url']; ?>" target="_blank" title="<?php print $link['MouseOverText']; ?>" class="external-link">
<?php if ($link['Icon']): ?><img src="<?php print $link['Icon']?>" /><?php endif; ?><?php print $link['Name']; ?>
</a>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
</div>
<div class="span-13">
<table cellpadding="2" cellspacing="0" border="0" class="citation" summary="<?php print t('Bibliographic Details'); ?>">
<?php foreach ($record->items as $item): ?>
<?php if (!empty($item['Data'])): ?>
<tr valign="top">
<th width="150"><?php print t($item['Label']); ?>:</th>
<td><?php print auto_link($item['Data']); ?></td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($record->db_label): ?>
<tr valign="top">
<th width="150"><?php print t('Database'); ?>:</th>
<td><?php print check_plain($record->db_label); ?></td>
</tr>
<?php endif; ?>
<?php if ($record->full_text): ?>
<tr id="html" valign="top">
<td colspan="2" class="html">
<?php print $record->full_text; ?>
</td>
</tr>
<?php elseif ($record->access_level && !user_is_logged_in()): ?>
<tr id="html" valign="top">
<td colspan="2" class="html">
<p>
<?php print t('The full text cannot be displayed to guests.'); ?>
<br />
<?php $link = '<a href="' . url('user') . '">' . t('Login') . '</a>'; ?>
<strong><?php print sprintf(t('%s for full access.'), $link); ?></strong>
</p>
</td>
</tr>
<?php endif; ?>
</table>
</div>
<div class="span-4">
<?php if ($record->medium_thumb_link): ?>
<img src="<?php print check_url($record->medium_thumb_link); ?>" class="book-jacket" alt="<?php print t('Book jacket')?>"/>
<?php endif; ?>
<?php if ($record->publication_type): ?>
<p><?php print check_plain($record->publication_type); ?></p>
<?php endif; ?>
</div>
<div class="clear"></div>
</div>
<?php endif; ?>
<div id="spinner" class="spinner"></div>

143
ebsco/templates/ebsco-results.tpl.php

@ -0,0 +1,143 @@
<?php
/**
* @file
* Default theme implementation for displaying EBSCO results.
*
* @see template_preprocess_ebsco_results()
*/
?>
<?php if ($records): ?>
<?php print t('Showing'); ?>
<strong><?php print $record_start; ?></strong> - <strong><?php print $record_end; ?></strong>
<?php print t('of'); ?> <strong><?php print $record_count; ?></strong>
<?php if ($search_view == 'basic'): ?>
<?php print t('for search')?>: <strong>'<?php print check_plain($lookfor); ?>'</strong>
<?php endif; ?>
<?php if ($search_time): ?>
, <?php print t('query time'); ?>: <?php print check_plain(round($search_time, 2)); ?>s
<?php endif; ?>
<?php print $sort_form; ?>
<?php print $pager; ?>
<?php if (!user_is_logged_in()): ?>
<?php $link = '<a href="' . url('user') . '">' . t('Login') . '</a>'; ?>
<p class="top-login-message">
<?php print sprintf(t('Hello, Guest. %s for full access.'), $link); ?>
</p>
<?php endif; ?>
<ol class="search-results ebsco">
<?php foreach ($records as $record): ?>
<?php
$id = check_plain($record->record_id());
$recordUrl = url('ebsco/result', array('query' => array('id' => $id)));
$fulltextUrl = url('ebsco/fulltext', array('query' => array('id' => $id)));
$pdfUrl = url('ebsco/pdf', array('query' => array('id' => $id)));
?>
<li>
<div class="record-number floatleft">
<?php print $record->result_id; ?>
</div>
<div class="result floatleft">
<div class="span-2">
<?php if ($record->small_thumb_link): ?>
<a href="<?php print $recordUrl; ?>" class="_record_link">
<img src="<?php print $record->small_thumb_link; ?>" class="book-jacket" alt="<?php print t('Book jacket'); ?>"/>
</a>
<?php endif; ?>
</div>
<div class="span-9">
<div class="result-line1">
<?php if ($record->access_level == '1'): ?>
<p>
<?php
$label = '<strong>' . check_plain($record->db_label) . '</strong>';
$link = '<a href="' . url('user') . '">' . t('Login') . '</a>';
?>
<?php print sprintf(t('This result from %s cannot be displayed to guests.'), $label); ?>
<br />
<strong><?php print sprintf(t('%s for full access.'), $link); ?></strong>
</p>
<?php elseif ($record->title): ?>
<a href="<?php print $recordUrl; ?>" class="title _record_link">
<?php print $record->title; ?>
</a>
<?php endif; ?>
</div>
<div class="result-line2">
<?php if (!empty($record->authors)): ?>
<p>
<?php print t('by'); ?>
<?php print $record->authors; ?>
</p>
<?php endif; ?>
<?php if (!empty($record->source)): ?>
<p>
<?php print t('Published in'); ?>
<?php print $record->source; ?>
</p>
<?php endif; ?>
</div>
<div class="result-line3">
<?php if (!empty($record->summary)): ?>
<cite><?php print $record->summary; ?></cite>
<br />
<?php endif; ?>
<?php if (!empty($record->subjects)): ?>
<strong><?php print t('Subjects'); ?></strong>:
<span class="quotestart"><?php print str_replace('<br />', ', ', $record->subjects); ?></span>
<?php endif; ?>
</div>
<?php if (!empty($record->custom_links)): ?>
<div class="result-line4">
<ul class="custom-links">
<?php foreach ($record->custom_links as $link): ?>
<li>
<a href="<?php print $link['Url']; ?>" target="_blank" title="<?php print $link['MouseOverText']; ?>" class="external-link">
<?php if ($link['Icon']): ?><img src="<?php print $link['Icon']?>" /><?php endif; ?><?php print $link['Name']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<div class="result-line5">
<?php if ($record->full_text_availability): ?>
<a href="<?php print $fulltextUrl; ?>#html" class="icon html fulltext _record_link">
<?php print t('HTML full text'); ?>
</a>
&nbsp; &nbsp;
<?php endif; ?>
<?php if ($record->pdf_availability): ?>
<a href="<?php print $pdfUrl; ?>" class="icon pdf fulltext">
<?php print t('PDF full text'); ?>
</a>
<?php endif; ?>
</div>
</div>
</div>
<div class="clear"></div>
</li>
<?php endforeach; ?>
</ol>
<?php print $pager; ?>
<?php elseif (!empty($lookfor)) : ?>
<h2><?php print t('Your search did not match any resources.');?></h2>
<?php print search_help('search#noresults', drupal_help_arg()); ?>
<?php endif; ?>
<div id="spinner" class="spinner"></div>

149
ebsco/templates/ebsco-side-facets.tpl.php

@ -0,0 +1,149 @@
<?php
/**
* @file
* Display the sidebar block with facets filters
*
* @see template_preprocess_ebsco_side_facets()
*/
?>
<?php
$limiters = array_slice($limiters, 0, 3);
?>
<div class="sidegroup">
<?php if ($record_count >= 0): ?>
<h2><?php print t('Narrow Search')?></h2>
<form name="updateForm" action="<?php print url('ebsco/results'); ?>" method="get">
<?php if ($search_params): ?>
<span>
<?php foreach($search_params as $k1 => $v1): ?>
<?php if (is_array($v1)): ?>
<?php foreach($v1 as $k2 => $v2): ?>
<?php if (is_array($v2)): ?>
<?php foreach($v2 as $k3 => $v3): ?>
<input type="hidden" name="<?php print $k1; ?>[<?php print $k2; ?>][<?php print $k3; ?>]" value="<?php print check_plain($v3); ?>" />
<?php endforeach; ?>
<?php else: ?>
<input type="hidden" name="<?php print $k1; ?>[<?php print $k2; ?>]" value="<?php print check_plain($v2); ?>" />
<?php endif; ?>
<?php endforeach; ?>
<?php else: ?>
<input type="hidden" name="<?php print $k1; ?>" value="<?php print check_plain($v1); ?>" />
<?php endif; ?>
<?php endforeach; ?>
</span>
<?php endif; ?>
<?php if (!empty($filters)): ?>
<dl class="narrow-list navmenu filters">
<dt><?php print t('Remove Filters'); ?></dt>
<?php foreach ($filters as $filter): ?>
<?php
$removeLink = remove_filter_link($filter);
?>
<dd>
<a href="<?php print $removeLink; ?>" class="icon13 expanded">
<?php print t($filter['displayField']); ?>: <?php print t($filter['displayValue']); ?>
</a>
</dd>
<?php endforeach; ?>
</dl>
<?php endif; ?>
<dl class="narrow-list navmenu">
<dt><?php print t('Limit Results'); ?></dt>
<?php foreach ($limiters as $limiter): ?>
<dd>
<?php if ($limiter['Type'] == 'multiselectvalue'): ?>
<label for="<?php print check_plain($limiter['Id']); ?>">
<?php print t($limiter['Label']); ?>
</label><br />
<select name="filter[]" multiple="multiple" id="<?php print check_plain($limiter['Id']); ?>">
<option value=""><?php print t('All'); ?></option>
<?php foreach ($limiter['Values'] as $option): ?>
<option value="<?php print check_plain($option['Action']); ?>"<?php $option['selected'] ? ' selected="selected"' : ''; ?>>
<?php print check_plain($option['Value']); ?>
</option>
<?php endforeach; ?>
</select>
<?php else: ?>
<input type="checkbox" name="filter[]" value="<?php print check_plain(str_replace('value', 'y', $limiter['Action'])); ?>"
<?php print $limiter['selected'] ? ' checked="checked"' : ''; ?> id="<?php print check_plain($limiter['Id']); ?>"
/>
<label for="<?php print check_plain($limiter['Id']); ?>">
<?php print check_plain(t($limiter['Label'])); ?>
</label>
<?php endif; ?>
</dd>
<?php endforeach; ?>
</dl>
<dl class="narrow-list navmenu">
<?php if ($expanders): ?>
<dt><?php print t('Expand Results'); ?></dt>
<?php endif; ?>
<?php foreach($expanders as $expander): ?>
<dd>
<input type="checkbox" name="filter[]" value="<?php print check_plain($expander['Action']); ?>"
<?php print $expander['selected'] ? ' checked="checked"' : ''; ?> id="<?php print check_plain($expander['Id']); ?>"
/>
<label for="<?php print check_plain($expander['Id']); ?>">
<?php print check_plain(t($expander['Label'])); ?>
</label>
</dd>
<?php endforeach; ?>
<dd class="submit">
<input type="submit" name="submit" class="form-submit" value="<?php print t('Update'); ?>" />
</dd>
</dl>
<?php if (!empty($facets)): ?>
<?php foreach ($facets as $title => $cluster): ?>
<dl id="facet-<?php print check_plain(t($title)); ?>" class="narrow-list navmenu expandable">
<dt>
<span class="icon13 collapsed">
<?php print check_plain(t($cluster['Label'])); ?>
</span>
</dt>
</dl>
<dl class="narrow-list navmenu offscreen" id="narrowGroupHidden_<?php print check_plain($title); ?>">
<?php foreach ($cluster['Values'] as $index => $facet): ?>
<?php if ($facet['applied']): ?>
<dd>
<?php print check_plain($facet['Value']); ?>
<span class="icon16 tick"></span>
</dd>
<?php else: ?>
<dd>
<input type="checkbox" name="filter[]" value="<?php print check_plain($facet['Action']); ?>"
id="filter<?php print check_plain($index); ?>"
/>
<label for="filter<?php print check_plain($index); ?>">
<a href="<?php print url('ebsco/results', array('query' => array_merge($link_search_params, array('filter[]' => $facet['Action'])))); ?>">
<?php print check_plain($facet['Value']); ?>
</a>
(<?php print check_plain($facet['Count']); ?>)
</label>
</dd>
<?php endif; ?>
<?php endforeach; ?>
<dd>
<p class="submit">
<input type="submit" class="form-submit" name="submit" value="<?php print t('Update'); ?>" />
</p>
<a href="javascript:void(0)" class="expandable">
<?php print t('Less'); ?> ...
</a>
</dd>
</dl>
<?php endforeach; ?>
<?php endif; ?>
</form>
<?php endif; ?>
</div>
Loading…
Cancel
Save