You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
11 KiB
340 lines
11 KiB
<?php |
|
/** |
|
* @file |
|
* Contains helper functions for working with Relais requests. |
|
*/ |
|
|
|
/** |
|
* Clean the form content before sending it to relais or logging it. |
|
* |
|
* @param $value |
|
* @param $key |
|
*/ |
|
|
|
use Drupal\Component\Utility\Xss; |
|
use Drupal\Component\Utility\Html; |
|
|
|
function upei_roblib_ill_check_arr_item(&$value, $key) |
|
{ |
|
if (is_array($value)) { |
|
array_walk($value, 'upei_roblib_ill_check_arr_item'); |
|
} |
|
else { |
|
$value = Xss::filter($value); |
|
} |
|
} |
|
|
|
/** |
|
* Removes empty elements and drupal specific elements from an array |
|
* |
|
* @param $values |
|
* A drupal form_state['values] array |
|
* |
|
* @return array |
|
* An array where the keys in the array that have empty values are removed and |
|
* drupal specific elements are removed. |
|
*/ |
|
function upei_roblib_ill_clean_array($values) |
|
{ |
|
$arr = array_filter($values); |
|
if (isset($arr['ISSN'])) { |
|
$arr['ISSN'] = [$arr['ISSN']]; |
|
} |
|
if (isset($arr['ISBN'])) { |
|
$arr['ISBN'] = [$arr['ISBN']]; |
|
} |
|
// The below checks are due to ebscos habit of sending sending the same info in both atitle and title etc. |
|
if (isset($arr['Genre']) && $arr['Genre'] == 'article' && isset($arr['Author'])) { |
|
// We want ArticleAuthor |
|
unset($arr['Author']); |
|
} |
|
if (isset($arr['Genre']) && $arr['Genre'] == 'book' && isset($arr['ArticleAuthor'])) { |
|
// We want Author |
|
unset($arr['ArticleAuthor']); |
|
} |
|
if (isset($arr['Genre']) && $arr['Genre'] == 'book' && isset($arr['ArticleTitle'])) { |
|
// We want Title only |
|
unset($arr['ArticleTitle']); |
|
} |
|
if (isset($arr['doi'])) { |
|
$arr['AdditionalNumbers'] = $arr['doi']; |
|
} |
|
unset($arr['form_build_id']); |
|
unset($arr['form_token']); |
|
unset($arr['form_id']); |
|
unset($arr['op']); |
|
unset($arr['submit']); |
|
unset($arr['next']); |
|
unset($arr['certify']); |
|
unset($arr['doi']); |
|
unset($arr['doi_button']); |
|
unset($arr['honeypot_time']); |
|
array_walk($arr, 'upei_roblib_ill_check_arr_item'); |
|
return $arr; |
|
} |
|
|
|
function upei_roblib_ill_build_err_msg($msg_from_server) |
|
{ |
|
$campus_id = Link::fromTextAndUrl(t('Campus ID'), Url::fromUri('http://www.upei.ca/vpaf/campuscard')); |
|
//$campus_id = l(t('Campus ID'), 'http://www.upei.ca/vpaf/campuscard'); |
|
$ill_email = Link::fromTextAndUrl('ill@upei.ca', Url::fromUri('mailto:ill@upei.ca')); |
|
//$ill_email = l(t('ill@upei.ca'), 'mailto:ill@upei.ca'); |
|
$phone = Link::fromTextAndUrl('902-566-0583', Url::fromUri('tel:902-566-0353')); |
|
//$phone = l(t('902-566-0583'), 'tel:902-566-0353'); |
|
$server_response = !empty($msg_from_server) ? 'Server Response: ' . $msg_from_server : ''; |
|
return t('Oops. Something went wrong.<br />Check the "Your Last Name" and "Your Campus ID" fields - those two need to match what is on file |
|
. (Your @campus_id appears as the NUMBER near the middle of your campus card). If you do not have a @campus_id, please contact the Robertson Library Service Desk, or, |
|
call @phone. Note: if you are a student taking online courses only, please email @ill_email.<br />@msg_from_server', |
|
[ |
|
'@campus_id' => $campus_id->toString(), |
|
'@ill_email' => $ill_email->toString(), |
|
'@phone' => $phone->toString(), |
|
'@msg_from_server' => $server_response, |
|
]); |
|
} |
|
|
|
/** |
|
* Authenticate against Evergreen and return an auth token. |
|
* |
|
* @param string $base_url |
|
* The base Evergreen URL. |
|
* @param string $username |
|
* The Evergreen staff username. |
|
* @param string $password |
|
* The Evergreen staff password. |
|
* |
|
* @return string|null |
|
* The auth token, or NULL on failure. |
|
*/ |
|
function upei_roblib_ill_evergreen_login($base_url, $username, $password) { |
|
$gateway_url = rtrim($base_url, '/') . '/osrf-gateway-v1'; |
|
$client = \Drupal::httpClient(); |
|
|
|
// Step 1: Get the seed/nonce for the username. |
|
$seed_response = $client->get($gateway_url, [ |
|
'timeout' => 10, |
|
'query' => [ |
|
'service' => 'open-ils.auth', |
|
'method' => 'open-ils.auth.authenticate.init', |
|
'param' => '"' . $username . '"', |
|
], |
|
]); |
|
$seed_data = json_decode((string) $seed_response->getBody(), TRUE); |
|
$seed = $seed_data['payload'][0] ?? NULL; |
|
if (empty($seed)) { |
|
\Drupal::logger('upei_roblib_ill')->error('Evergreen auth init failed: no seed returned.'); |
|
return NULL; |
|
} |
|
|
|
// Step 2: Authenticate with the hashed password. |
|
$hashed_password = md5($seed . md5($password)); |
|
$auth_response = $client->get($gateway_url, [ |
|
'timeout' => 10, |
|
'query' => [ |
|
'service' => 'open-ils.auth', |
|
'method' => 'open-ils.auth.authenticate.complete', |
|
'param' => json_encode([ |
|
'username' => $username, |
|
'password' => $hashed_password, |
|
'type' => 'staff', |
|
]), |
|
], |
|
]); |
|
$auth_data = json_decode((string) $auth_response->getBody(), TRUE); |
|
$auth_result = $auth_data['payload'][0] ?? NULL; |
|
|
|
if (empty($auth_result) || ($auth_result['ilsevent'] ?? -1) != 0) { |
|
$text_code = $auth_result['textcode'] ?? 'unknown'; |
|
\Drupal::logger('upei_roblib_ill')->error('Evergreen auth failed: @code', [ |
|
'@code' => $text_code, |
|
]); |
|
return NULL; |
|
} |
|
|
|
return $auth_result['payload']['authtoken'] ?? NULL; |
|
} |
|
|
|
/** |
|
* Lookup the user in Evergreen via the REST API and verify the surname matches. |
|
* |
|
* Authenticates with Evergreen using staff credentials, then retrieves the |
|
* patron by user ID and compares the family_name field against the provided |
|
* surname. |
|
* |
|
* @param string $user_id |
|
* The Evergreen user ID. |
|
* @param string $surname |
|
* The surname to check against. |
|
* |
|
* @return bool |
|
* TRUE if the surname matches, FALSE otherwise. |
|
*/ |
|
function upei_roblib_ill_authenticate($user_id, $surname): bool |
|
{ |
|
if (empty($user_id) || empty($surname)) { |
|
return FALSE; |
|
} |
|
|
|
$config = \Drupal::config('upei_roblib_ill.settings'); |
|
$evergreen_api_url = $config->get('evergreen_api_url'); |
|
$eg_username = $config->get('evergreen_username'); |
|
$eg_password = $config->get('evergreen_password'); |
|
|
|
if (empty($evergreen_api_url) || empty($eg_username) || empty($eg_password)) { |
|
\Drupal::logger('upei_roblib_ill')->error('Evergreen API URL or credentials are not configured.'); |
|
return FALSE; |
|
} |
|
|
|
try { |
|
// Authenticate to get an auth token. |
|
$auth_token = upei_roblib_ill_evergreen_login($evergreen_api_url, $eg_username, $eg_password); |
|
if (empty($auth_token)) { |
|
return FALSE; |
|
} |
|
|
|
// Retrieve the patron by user ID using the auth token. |
|
$gateway_url = rtrim($evergreen_api_url, '/') . '/osrf-gateway-v1'; |
|
$response = \Drupal::httpClient()->get($gateway_url, [ |
|
'timeout' => 10, |
|
'query' => [ |
|
'service' => 'open-ils.actor', |
|
'method' => 'open-ils.actor.user.retrieve', |
|
'param' => ['"' . $auth_token . '"', '"' . $user_id . '"'], |
|
], |
|
]); |
|
|
|
$data = json_decode((string) $response->getBody(), TRUE); |
|
|
|
$patron = $data['payload'][0] ?? NULL; |
|
if (empty($patron) || isset($patron['ilsevent'])) { |
|
$evt = $patron['textcode'] ?? 'no data'; |
|
\Drupal::logger('upei_roblib_ill')->warning('Evergreen REST API returned no patron for user ID @user_id: @evt', [ |
|
'@user_id' => $user_id, |
|
'@evt' => $evt, |
|
]); |
|
return FALSE; |
|
} |
|
|
|
$evergreen_surname = $patron['family_name'] ?? ''; |
|
|
|
// Case-insensitive comparison of the Evergreen surname and provided surname. |
|
if (strcasecmp(trim($evergreen_surname), trim($surname)) === 0) { |
|
return TRUE; |
|
} |
|
|
|
\Drupal::logger('upei_roblib_ill')->warning('Evergreen authentication failed for user ID @user_id. Expected surname: @surname, got: @evergreen_surname', [ |
|
'@user_id' => $user_id, |
|
'@surname' => $surname, |
|
'@evergreen_surname' => $evergreen_surname, |
|
]); |
|
|
|
return FALSE; |
|
|
|
} |
|
catch (\Exception $e) { |
|
\Drupal::logger('upei_roblib_ill')->error('Failed to connect to Evergreen REST API: @message', [ |
|
'@message' => $e->getMessage(), |
|
]); |
|
return FALSE; |
|
} |
|
} |
|
|
|
/** |
|
* Allows us to ask for _REQUEST variables that may or may not exist without |
|
* generating a php warning. Also does some formatting for certain variables. |
|
* |
|
* @param string $variable |
|
* The name of the $_REQUEST variable to check |
|
* |
|
* @return string |
|
* The value of the $_REQUEST variable or an empty string. |
|
*/ |
|
function upei_roblib_ill_get_request_variable($variable) |
|
{ |
|
if ($variable == 'author' && empty($_REQUEST[$variable])) { |
|
//google scholar usually sends auinit aulast instead of author |
|
$initial = isset($_REQUEST['auinit']) ?Html::escape($_REQUEST['auinit']) : NULL; |
|
$last_name = isset($_REQUEST['aulast']) ?Html::escape($_REQUEST['aulast']) : NULL; |
|
return !empty($last_name) ? $last_name . ',' . $initial : ''; |
|
} |
|
if ($variable == 'issn' && !empty($_REQUEST[$variable])) { |
|
// ebsco sometimes sends garbage as issns verify this is a valid issn before displaying the value in the form. |
|
return preg_match('/^\d{4}-?\d{3}[\dxX]$/', $_REQUEST[$variable]) ?Html::escape($_REQUEST[$variable]) : ''; |
|
} |
|
// ebsco sometimes returns bookitem we only understand chapter |
|
if (($variable == 'genre' && !empty($_REQUEST[$variable])) && $_REQUEST[$variable] == 'bookitem') { |
|
return 'chapter'; |
|
} |
|
return isset($_REQUEST[$variable]) ?Html::escape($_REQUEST[$variable]) : ''; |
|
} |
|
|
|
|
|
function upei_roblib_ill_get_doi_from_request() |
|
{ |
|
return (!empty($_REQUEST['doi'])) ? $_REQUEST['doi'] : upei_roblib_ill_get_doi_from_id(); |
|
} |
|
|
|
function upei_roblib_ill_get_doi_from_id() |
|
{ |
|
if (!empty($_REQUEST['ID'])) { |
|
return (strpos($_REQUEST['ID'], 'doi:') !== 0) ? '' : $_REQUEST['ID']; |
|
} |
|
return ''; |
|
} |
|
|
|
/** |
|
* Populates the requestInfo portion of a Relais request |
|
* |
|
* @param array $values |
|
* an array containing a 'Genre' element. |
|
* |
|
* @return array |
|
* The requestInfo portion of a Relais request |
|
*/ |
|
function upei_roblib_ill_request_info_array($values, $notes) |
|
{ |
|
$requestInfo = []; |
|
$genre = $values['Genre']; |
|
$requestInfo['DateSubmitted'] = date('Y-m-d H:i:s'); |
|
$requestInfo['Notes'] = $notes; |
|
if ($genre == 'book') { |
|
$requestInfo['ServiceType'] = 'L'; |
|
$requestInfo['ServiceLabel'] = "R"; |
|
//$requestInfo['RequestSource'] = "C"; |
|
} |
|
else { |
|
$requestInfo['ServiceType'] = 'X'; |
|
$requestInfo['ServiceLabel'] = "R"; |
|
//$requestInfo['RequestSource'] = "C"; |
|
} |
|
return $requestInfo; |
|
} |
|
|
|
/** |
|
* Creates a summary Table based on the biblio information in the form_state |
|
* array for display |
|
* |
|
* @param $form_state |
|
* |
|
* @return string |
|
*/ |
|
function upei_roblib_format_biblio_info($form_state) |
|
{ |
|
$values = $form_state->getValues(); |
|
$data = upei_roblib_ill_clean_array($values); |
|
$rows = []; |
|
foreach ($data as $key => $value) { |
|
if ($key == 'ISSN' || $key == 'ISBN') { |
|
$value = reset($value); |
|
} |
|
array_push($rows, [$key, $value]); |
|
} |
|
$output = [ |
|
'#theme' => 'table', |
|
'#rows' => $rows, |
|
'#prefix' => '<div class=upei-roblib-ill-biblio-info>', |
|
'#suffix' => '</div>', |
|
]; |
|
$html_output = \Drupal::service('renderer')->render($output); |
|
return $html_output; |
|
} |