diff --git a/config/schema/upei_roblib_ill.schema.yml b/config/schema/upei_roblib_ill.schema.yml
index e4f1e86..98affcc 100644
--- a/config/schema/upei_roblib_ill.schema.yml
+++ b/config/schema/upei_roblib_ill.schema.yml
@@ -26,3 +26,6 @@ upei_roblib_ill.settings:
rapid_ill_branch_name:
type: string
label: 'RapidILL Branch Name'
+ evergreen_api_url:
+ type: string
+ label: 'Evergreen API URL'
diff --git a/includes/db.inc b/includes/db.inc
index 3071dde..ae9bf69 100644
--- a/includes/db.inc
+++ b/includes/db.inc
@@ -5,42 +5,54 @@
*/
+use RapidIll\InsertRequest;
+
/**
* Log an ILL request
*
- * @param array $request
- * The request sent to Relais as an array (before it is encoded as JSON)
- * @param array $response
- * The response from Relais.
+ * @param \RapidIll\InsertRequest $request
+ * The request sent to RapidILL as an InsertRequest object.
+ * @param array|string $response
+ * The response from RapidILL or an error message.
*/
-function upei_roblib_ill_log_request($request, $response) {
- $time_submitted = isset($request['RequestInfo']['DateSubmitted']) ? $request['RequestInfo']['DateSubmitted'] : '';
- $relais_message = isset($response['ConfirmMessage']) ? $response['ConfirmMessage'] : $response['Problem']['Message'];
+function upei_roblib_ill_log_request(InsertRequest $request, $response) {
+ $soap_data = $request->toSoapArray();
+ $time_submitted = time();
+ $relais_message = is_array($response) ? (isset($response['ConfirmMessage']) ? $response['ConfirmMessage'] : ($response['Problem']['Message'] ?? '')) : (string) $response;
+
+ $patron_firstname = '';
+ $patron_lastname = '';
+ if (!empty($soap_data['PatronName'])) {
+ $parts = explode(' ', $soap_data['PatronName'], 2);
+ $patron_firstname = trim($parts[0] ?? '');
+ $patron_lastname = trim($parts[1] ?? '');
+ }
+
$connection = \Drupal::service('database');
try {
$connection->insert('upei_roblib_ill_request')
->fields([
- 'patron_id' => $request['DeliveryAddress']['campus_id'],
- 'patron_firstname' => $request['DeliveryAddress']['FirstName'],
- 'patron_lastname' => $request['DeliveryAddress']['Surname'],
- 'patron_type' => $request['DeliveryAddress']['patron_type'],
- 'patron_department' => $request['DeliveryAddress']['Department'],
- 'patron_email' => $request['DeliveryAddress']['DeliveryAddress'],
- 'notes' => isset($request['DeliveryAddress']['notes']) ? $request['DeliveryAddress']['notes'] : '',
- 'genre' => isset($request['BibliographicInfo']['Genre']) ? $request['BibliographicInfo']['Genre'] : '',
- 'doi' => isset($request['BibliographicInfo']['AdditionalNumbers']) ? $request['BibliographicInfo']['AdditionalNumbers'] : '',
- 'author' => isset($request['BibliographicInfo']['Author']) ? $request['BibliographicInfo']['Author'] : '',
- 'citation_date' => isset($request['BibliographicInfo']['Date']) ? $request['BibliographicInfo']['Date'] : '',
- 'title' => isset($request['BibliographicInfo']['Title']) ? $request['BibliographicInfo']['Title'] : '',
- 'atitle' => isset($request['BibliographicInfo']['ArticleTitle']) ? $request['BibliographicInfo']['ArticleTitle'] : '',
- 'issn' => isset($request['BibliographicInfo']['ISSN'][0]) ? $request['BibliographicInfo']['ISSN'][0] : '',
- 'isbn' => isset($request['BibliographicInfo']['ISBN'][0]) ? $request['BibliographicInfo']['ISBN'][0] : '',
- 'article_author' => isset($request['BibliographicInfo']['ArticleAuthor']) ? $request['BibliographicInfo']['ArticleAuthor'] : '',
- 'volume' => isset($request['BibliographicInfo']['Volume']) ? $request['BibliographicInfo']['Volume'] : '',
- 'issue' => isset($request['BibliographicInfo']['Issue']) ? $request['BibliographicInfo']['Issue'] : '',
- 'pages_requested' => isset($request['BibliographicInfo']['PagesRequested']) ? $request['BibliographicInfo']['PagesRequested'] : '',
- 'time_submitted' => strtotime($time_submitted),
- 'relais_request_id' => isset($response['RequestNumber']) ? $response['RequestNumber'] : '-1',
+ 'patron_id' => $soap_data['PatronId'] ?? '',
+ 'patron_firstname' => $patron_firstname,
+ 'patron_lastname' => $patron_lastname,
+ 'patron_type' => '',
+ 'patron_department' => $soap_data['PatronDepartment'] ?? '',
+ 'patron_email' => $soap_data['PatronEmail'] ?? '',
+ 'notes' => $soap_data['PatronNotes'] ?? '',
+ 'genre' => $soap_data['RapidRequestType'] ?? '',
+ 'doi' => '',
+ 'author' => $soap_data['ArticleAuthor'] ?? '',
+ 'citation_date' => $soap_data['PatronJournalYear'] ?? '',
+ 'title' => $soap_data['PatronJournalTitle'] ?? '',
+ 'atitle' => $soap_data['ArticleTitle'] ?? '',
+ 'issn' => $soap_data['SuggestedIssns']['string'][0] ?? '',
+ 'isbn' => $soap_data['SuggestedIsbns']['string'][0] ?? '',
+ 'article_author' => $soap_data['ArticleAuthor'] ?? '',
+ 'volume' => $soap_data['JournalVol'] ?? '',
+ 'issue' => $soap_data['JournalIssue'] ?? '',
+ 'pages_requested' => $soap_data['ArticlePages'] ?? '',
+ 'time_submitted' => $time_submitted,
+ 'relais_request_id' => is_array($response) && isset($response['RequestNumber']) ? $response['RequestNumber'] : '-1',
'relais_message' => substr($relais_message, 0, 254),
])->execute();
} catch (Exception $e) {
diff --git a/includes/rapidill.inc b/includes/rapidill.inc
index 9a72f6d..d6a366f 100644
--- a/includes/rapidill.inc
+++ b/includes/rapidill.inc
@@ -217,8 +217,7 @@ class RapidIllRequestHandler {
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/db');
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/utilities');
- // Build the Relais-style array for logging purposes.
- $relais_arr = upei_roblib_ill_build_relais_arr($form_state);
+ $insert_request = $this->buildInsertRequest($form_state);
try {
$client = $this->createClient();
@@ -227,12 +226,10 @@ class RapidIllRequestHandler {
$error_response = [
'ConfirmMessage' => 'RapidILL is not configured. Please contact the library.',
];
- upei_roblib_ill_log_request($relais_arr, $error_response);
+ upei_roblib_ill_log_request($insert_request, $error_response);
return $error_response;
}
- $insert_request = $this->buildInsertRequest($form_state);
-
try {
/** @var \RapidIll\InsertResponse $response */
$response = $client->insertRequest($insert_request);
@@ -245,7 +242,7 @@ class RapidIllRequestHandler {
$error_response = [
'ConfirmMessage' => 'Error communicating with RapidILL: ' . $e->getMessage(),
];
- upei_roblib_ill_log_request($relais_arr, $error_response);
+ upei_roblib_ill_log_request($insert_request, $error_response);
return $error_response;
}
@@ -263,7 +260,7 @@ class RapidIllRequestHandler {
];
}
- upei_roblib_ill_log_request($relais_arr, $result);
+ upei_roblib_ill_log_request($insert_request, $result);
return $result;
}
diff --git a/includes/utilities.inc b/includes/utilities.inc
index f869a0c..50c2216 100644
--- a/includes/utilities.inc
+++ b/includes/utilities.inc
@@ -14,7 +14,8 @@
use Drupal\Component\Utility\Xss;
use Drupal\Component\Utility\Html;
-function upei_roblib_ill_check_arr_item(&$value, $key) {
+function upei_roblib_ill_check_arr_item(&$value, $key)
+{
if (is_array($value)) {
array_walk($value, 'upei_roblib_ill_check_arr_item');
}
@@ -33,7 +34,8 @@ function upei_roblib_ill_check_arr_item(&$value, $key) {
* 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) {
+function upei_roblib_ill_clean_array($values)
+{
$arr = array_filter($values);
if (isset($arr['ISSN'])) {
$arr['ISSN'] = [$arr['ISSN']];
@@ -71,6 +73,95 @@ function upei_roblib_ill_clean_array($values) {
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.
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.
@msg_from_server',
+ [
+ '@campus_id' => $campus_id->toString(),
+ '@ill_email' => $ill_email->toString(),
+ '@phone' => $phone->toString(),
+ '@msg_from_server' => $server_response,
+ ]);
+}
+
+/**
+ * Lookup the user in Evergreen and verify the surname matches.
+ *
+ * @param string $campus_id
+ * The user's campus ID / barcode.
+ * @param string $surname
+ * The surname to check against.
+ *
+ * @return bool
+ * TRUE if the surname matches, FALSE otherwise.
+ */
+function upei_roblib_ill_authenticate($campus_id, $surname): bool
+{
+ if (empty($campus_id) || empty($surname)) {
+ return FALSE;
+ }
+
+ $config = \Drupal::config('upei_roblib_ill.settings');
+ $evergreen_api_url = $config->get('evergreen_api_url');
+ if (empty($evergreen_api_url)) {
+ \Drupal::logger('upei_roblib_ill')->error('Evergreen API URL is not configured.');
+ return FALSE;
+ }
+
+ // Construct the PatronAPI dump URL.
+ // Format: {evergreen_api_url}/api/patronapi/{campus_id}/dump
+ $url = rtrim($evergreen_api_url, '/') . '/api/patronapi/' . urlencode($campus_id) . '/dump';
+
+ try {
+ $response = \Drupal::httpClient()->get($url, [
+ 'timeout' => 10,
+ ]);
+
+ $data = (string)$response->getBody();
+
+ // The PatronAPI dump endpoint returns data in a plain text/HTML format
+ // looking like `PATRN NAME[p]=Smith, John`.
+ if (preg_match('/PATRN NAME\[p\]=([^\[<]+)/i', $data, $matches)) {
+ $patron_name = trim($matches[1]);
+
+ // Usually "Lastname, Firstname"
+ $name_parts = explode(',', $patron_name);
+ if (count($name_parts) > 0) {
+ $evergreen_surname = trim($name_parts[0]);
+
+ // Case-insensitive comparison of the extracted surname and provided surname.
+ if (strcasecmp($evergreen_surname, trim($surname)) === 0) {
+ return TRUE;
+ }
+ }
+ }
+
+ // Log failure for debugging.
+ \Drupal::logger('upei_roblib_ill')->warning('Evergreen authentication failed for @campus_id. Expected surname: @surname', [
+ '@campus_id' => $campus_id,
+ '@surname' => $surname,
+ ]);
+
+ return FALSE;
+
+ }
+ catch (\Exception $e) {
+ \Drupal::logger('upei_roblib_ill')->error('Failed to connect to Evergreen 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.
@@ -81,30 +172,33 @@ function upei_roblib_ill_clean_array($values) {
* @return string
* The value of the $_REQUEST variable or an empty string.
*/
-function upei_roblib_ill_get_request_variable($variable) {
+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;
+ $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]) : '';
+ 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]) : '';
+ return isset($_REQUEST[$variable]) ?Html::escape($_REQUEST[$variable]) : '';
}
-function upei_roblib_ill_get_doi_from_request() {
+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() {
+function upei_roblib_ill_get_doi_from_id()
+{
if (!empty($_REQUEST['ID'])) {
return (strpos($_REQUEST['ID'], 'doi:') !== 0) ? '' : $_REQUEST['ID'];
}
@@ -120,7 +214,8 @@ function upei_roblib_ill_get_doi_from_id() {
* @return array
* The requestInfo portion of a Relais request
*/
-function upei_roblib_ill_request_info_array($values, $notes) {
+function upei_roblib_ill_request_info_array($values, $notes)
+{
$requestInfo = [];
$genre = $values['Genre'];
$requestInfo['DateSubmitted'] = date('Y-m-d H:i:s');
@@ -128,12 +223,12 @@ function upei_roblib_ill_request_info_array($values, $notes) {
if ($genre == 'book') {
$requestInfo['ServiceType'] = 'L';
$requestInfo['ServiceLabel'] = "R";
- //$requestInfo['RequestSource'] = "C";
+ //$requestInfo['RequestSource'] = "C";
}
else {
$requestInfo['ServiceType'] = 'X';
$requestInfo['ServiceLabel'] = "R";
- //$requestInfo['RequestSource'] = "C";
+ //$requestInfo['RequestSource'] = "C";
}
return $requestInfo;
}
@@ -146,7 +241,8 @@ function upei_roblib_ill_request_info_array($values, $notes) {
*
* @return string
*/
-function upei_roblib_format_biblio_info($form_state) {
+function upei_roblib_format_biblio_info($form_state)
+{
$values = $form_state->getValues();
$data = upei_roblib_ill_clean_array($values);
$rows = [];
@@ -164,4 +260,4 @@ function upei_roblib_format_biblio_info($form_state) {
];
$html_output = \Drupal::service('renderer')->render($output);
return $html_output;
-}
+}
\ No newline at end of file
diff --git a/src/Form/RoblibIllLoanForm.php b/src/Form/RoblibIllLoanForm.php
index 86f20f3..0b28bea 100644
--- a/src/Form/RoblibIllLoanForm.php
+++ b/src/Form/RoblibIllLoanForm.php
@@ -10,19 +10,22 @@ use Drupal\Core\Form\FormStateInterface;
*
* @author ppound
*/
-class RoblibIllLoanForm extends FormBase {
+class RoblibIllLoanForm extends FormBase
+{
/**
* {@inheritdoc}
*/
- public function getFormId() {
+ public function getFormId()
+ {
return 'roblib_ill_loan_form';
}
/**
* {@inheritdoc}
*/
- public function buildForm(array $form, FormStateInterface $form_state) {
+ public function buildForm(array $form, FormStateInterface $form_state)
+ {
if ($form_state->has('step') && $form_state->get('step') == 2) {
return $this->ill_auth_form($form, $form_state);
}
@@ -32,8 +35,10 @@ class RoblibIllLoanForm extends FormBase {
/**
* {@inheritdoc}
*/
- public function validateForm(array &$form, FormStateInterface $form_state) {
+ public function validateForm(array &$form, FormStateInterface $form_state)
+ {
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/relais');
+ \Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/utilities');
$values = $form_state->getValues();
if ($form_state->get('step') == 2) {
$is_valid_email = \Drupal::service('email.validator')->isValid($values['DeliveryAddress']);
@@ -46,29 +51,27 @@ class RoblibIllLoanForm extends FormBase {
$campus_id = $this->ill_form_message_id($values['campus_id']);
- $aid = upei_roblib_ill_authenticate($campus_id, $values['Surname']);
- if (is_array($aid) && isset($aid['Problem']['Message'])) {
- if (!empty($aid['Problem']['HR_Message'])) {
- $form_state->setErrorByName('campus_id', $aid['Problem']['HR_Message']);
- }
- $form_state->setErrorByName('Surname', $aid['Problem']['Message']);
+ $auth = upei_roblib_ill_authenticate($campus_id, $values['Surname']);
+ if (!$auth) {
+ $err = 'UserID or Surname do not match or not found.';
+ $form_state->setErrorByName('Surname', $err);
// Log invalid requests, we need to build the full array here to log it, even though we won't send it yet as auth has failed.
//$form_state->set('upei_roblib_ill_auth_form_storage') = $form_state->getValues();
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/db');
- $arr = upei_roblib_ill_build_relais_arr($form_state);
- upei_roblib_ill_log_request($arr, $aid);
- }
- else {
- $form_state->set('aid', $aid);
- }
- }
- $trigger = $form_state->getTriggeringElement();
- if($trigger['#value'] != 'Lookup DOI' && empty($form_state->get('step'))) {
- if(empty($form_state->getValue('Title'))){
- $form_state->setErrorByName('Title', t('Journal/Book Title is required.'));
+ \Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/rapidill');
+ $handler = new \RapidIllRequestHandler();
+ $response = $handler->buildInsertRequest($form_state);
+ upei_roblib_ill_log_request($response, $err);
}
- if(empty($form_state->getValue('Genre'))) {
- $form_state->setErrorByName('Title', t('Item Type is required.'));
+
+ $trigger = $form_state->getTriggeringElement();
+ if ($trigger['#value'] != 'Lookup DOI' && empty($form_state->get('step'))) {
+ if (empty($form_state->getValue('Title'))) {
+ $form_state->setErrorByName('Title', t('Journal/Book Title is required.'));
+ }
+ if (empty($form_state->getValue('Genre'))) {
+ $form_state->setErrorByName('Title', t('Item Type is required.'));
+ }
}
}
}
@@ -80,7 +83,8 @@ class RoblibIllLoanForm extends FormBase {
* @return mixed
* the campus id with leading zeros and leading/trailing whitespace removed.
*/
- function ill_form_message_id($id) {
+ function ill_form_message_id($id)
+ {
// Equinox made some changes to the database so we may not need to do
// this anymore.
// Doing this simple change for now in case things need to be reverted.
@@ -95,7 +99,8 @@ class RoblibIllLoanForm extends FormBase {
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
- public function submitStepOne(array &$form, FormStateInterface $form_state) {
+ public function submitStepOne(array &$form, FormStateInterface $form_state)
+ {
$trigger = $form_state->getTriggeringElement();
if ($trigger['#value'] != 'Lookup DOI') {
$form_state
@@ -108,7 +113,8 @@ class RoblibIllLoanForm extends FormBase {
/**
* {@inheritdoc}
*/
- public function submitForm(array &$form, FormStateInterface $form_state) {
+ public function submitForm(array &$form, FormStateInterface $form_state)
+ {
$trigger = $form_state->getTriggeringElement();
if ($trigger['#value'] == 'Lookup DOI') {
//Do nothing as this was just a DOI Lookup
@@ -122,11 +128,12 @@ class RoblibIllLoanForm extends FormBase {
'message' => $response['ConfirmMessage'],
'email' => $form_state->getValue('DeliveryAddress'),
'error' => $error,
- ];
+ ];
$form_state->setRedirect('roblib_ill.loan_form_finished', $parameters);
}
- public function doiCallback(array &$form, FormStateInterface $form_state) {
+ public function doiCallback(array &$form, FormStateInterface $form_state)
+ {
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/doi');
$doi = $form_state->getValue('doi');
$form = upei_roblib_ill_doi_get_data($form, $doi);
@@ -144,7 +151,8 @@ class RoblibIllLoanForm extends FormBase {
* @return array
* An array representing the bibliographic form.
*/
- function ill_request_form($form, &$form_state) {
+ function ill_request_form($form, &$form_state)
+ {
\Drupal::moduleHandler()->loadInclude('upei_roblib_ill', 'inc', 'includes/utilities');
$config = \Drupal::config('upei_roblib_ill.settings');
$form['#prefix'] = '